iOS-ASIHTTPRequest框架学习
本文转载至 http://www.cnblogs.com/A-Long-Way-Chris/p/3539679.html
前段时间在公司的产品中支持了够快网盘,用于云盘存储。
在这个过程中,学习到了很多新的知识,也遇到了很多问题,在此记录一下。
首先就够快的API总结一下。
一、请求参数中的签名。第一点是生成字符串,例如”2\n3\n1”,在C#中是不需要加上@前置符号的,这是我一个同事犯过的错误。第二点是签名算法,按照原文提示:将生成的字符利用client_secret作为key进行hmac-sha1加密,然后再进行base64 encode,最后对结果进行rfc3986 URL编码,即:encodeURI(base64_encode(hmac-sha1([string], [client_secret])))。OC的代码如下:
- (NSString*)getRequestSign:(NSString*)string
{
const char *cString = [string cStringUsingEncoding:NSUTF8StringEncoding];
const char *cSecret = [kCHRISGoKuaiClientSecret cStringUsingEncoding:NSUTF8StringEncoding]; char cHMAC[CC_SHA1_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA1, cSecret, strlen(cSecret), cString, strlen(cString), cHMAC); NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:CC_SHA1_DIGEST_LENGTH];
NSString *hash = [HMAC base64Encoding];
[HMAC release]; NSString *sign = (NSString*)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)hash, NULL, (CFStringRef)@"!*'();:@&=+$,/?%#[]", kCFStringEncodingUTF8);
return sign;
}
在此,需要先添加头文件引用:
#import <CommonCrypto/CommonHMAC.h>和#import <CommonCrypto/CommonCryptor.h>
二、删除和上传api中的路径参数。对象若为文件,则api中路径参数需要去掉首尾的”/”符号;对象若为文件夹,则api中需要在上述基础上,再在末尾加上一个”/”符号。
保存access_token。
在得到用户的access_token、expires_in、refresh_token以后,可以保存到设备端,避免繁琐的登陆授权操作。采用NSUserDefaults是不安全的,证书和密码之类的私密信息需要更为安全的keychain来保存。封装的keychain如下:
#import <Foundation/Foundation.h> @interface CHRISKeyChain : NSObject @property (readwrite, nonatomic, retain) NSDictionary* keyChainDic; + (id)keyChainForId:(NSString*)keyChainId; - (NSDictionary *)credentials; - (void)setCredentials:(NSDictionary *)credentials; - (void)deleteCredentials;
@end
#import "CHRISKeyChain.h" static NSMutableDictionary* g_keyChainDic = nil; @implementation CHRISKeyChain
@synthesize keyChainDic = _keyChainDic; + (id)keyChainForId:(NSString*)keyChainId
{
if (!g_keyChainDic)
{
g_keyChainDic = [[NSMutableDictionary dictionary] retain];
}
CHRISKeyChain* keyChainObject = [g_keyChainDic objectForKey:keyChainId];
if (!keyChainObject)
{
NSDictionary* keyChainDict = [NSDictionary dictionaryWithObjectsAndKeys:
(id)kSecClassGenericPassword, (id)kSecClass,
keyChainId, (id)kSecAttrService, nil];
keyChainObject = [[[CHRISKeyChain alloc] init] autorelease];
keyChainObject.keyChainDic = keyChainDict;
[g_keyChainDic setObject:keyChainObject forKey:keyChainId];
return keyChainObject;
}
return keyChainObject;
} - (void)dealloc
{
self.keyChainDic = nil;
[super dealloc];
} - (NSDictionary *)credentials
{
NSMutableDictionary *searchDict = [NSMutableDictionary dictionaryWithDictionary:_keyChainDic];
[searchDict setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
[searchDict setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];
[searchDict setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; NSDictionary *attrDict = nil;
OSStatus status = SecItemCopyMatching((CFDictionaryRef)searchDict, (CFTypeRef *)&attrDict);
[attrDict autorelease];
NSData *foundValue = [attrDict objectForKey:(id)kSecValueData]; if (status == noErr && foundValue)
{
return [NSKeyedUnarchiver unarchiveObjectWithData:foundValue];
}
if (status != errSecItemNotFound)
{
NSLog(@"error reading stored credentials (%ld)", status);
}
return nil;
} - (void)setCredentials:(NSDictionary *)credentials
{
NSData *credentialData = [NSKeyedArchiver archivedDataWithRootObject:credentials]; NSMutableDictionary *attrDict = [NSMutableDictionary dictionaryWithDictionary:_keyChainDic];
[attrDict setObject:credentialData forKey:(id)kSecValueData]; NSArray *version = [[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."];
if ([[version objectAtIndex:0] intValue] >= 4) {
[attrDict setObject:(id)kSecAttrAccessibleWhenUnlocked forKey:(id)kSecAttrAccessible];
} OSStatus status = noErr; if ([self credentials])
{
[attrDict removeObjectForKey:(id)kSecClass];
status = SecItemUpdate((CFDictionaryRef)_keyChainDic, (CFDictionaryRef)attrDict);
}
else
{
status = SecItemAdd((CFDictionaryRef)attrDict, NULL);
} if (status != noErr)
{
NSLog(@"error saving credentials (%ld)", status);
}
} - (void)deleteCredentials
{
OSStatus status = SecItemDelete((CFDictionaryRef)_keyChainDic); if (status != noErr)
{
NSLog(@"error deleting credentials (%ld)", status);
}
} @end
够快网盘之ASIHTTPRequest框架。
既然是网盘,必然涉及文件上传和下载等网络请求,这里采用了ASIHTTPRequest框架来实现网络请求和文件的上传、下载。
一、够快网盘的下载api采用get方式:
ASIHTTPRequest* request = [ASIHTTPRequest requestWithURL: url];
[request setCompletionBlock:^{
NSDictionary* params = [request.responseString objectFromJSONString];
....
}];
[request setFailedBlock:^{…}];
[request setStartedBlock:^{…}];
[request setBytesReceivedBlock:^(unsigned long long size, unsigned long long total){
Meta.synProgress =( (double)request.totalBytesRead + request.partialDownloadSize) / total;
}];
[request setDownloadDestinationPath: filePath];
[request setAllowCompressedResponse: NO];
[request setAllowResumeForFileDownloads: YES];
[request setShouldPresentCredentialsBeforeChallenge: YES];
[request setShowAccurateProress: YES];
[request startAsynchronous];
说明:url为NSURL对象;filePath为本地存储路径;BytesReceivedBlock可以用来显示当前下载进度的百分比。objectFromJSONString方法需要先添加JSONKit并引用头文件。
二、够快网盘的上传api步骤2采用了post multipart/form-data方式:
ASIFormDataRequest* request = [ASIHTTPRequest requestWithURL: url];
[request setPostValue: … forKey: …];
…..
[request setPostValue: @”file” forKey: @”filefield”];
request.requestMethod = @”POST”;
[request addRequestHeader:@”Content-Type” value:@”Multipart/form-data”]
[request setCompletionBlock:^{
NSDictionary* params = [request.responseString objectFromJSONString];
…..
}];
[request setFailedBlock:^{….}];
[request setStartedBlock:^{…..}];
[request setBytesReceivedBlock:^(unsigned long long size, unsigned long long total){
Meta.synProgress =( (double)request.totalBytesSent )/ total;
}];
[request setDownloadDestinationPath: filePath];
[request setAllowCompressedResponse: NO];
[request setAllowResumeForFileDownloads: YES];
[request setShouldPresentCredentialsBeforeChallenge: YES];
[request setShowAccurateProress: YES];
[request setShouldStreamPostFromDisk: YES];
[request setFile: localPath withFileName: [meta.path lastPathComponent] andContentType: meta.contentType forKey: @”file”];
[request startAsynchronous];
说明:[request setPostValue: @”file” forKey: @”filefield”];中的value必须和后面的forKey一致,这也符合api最后一个参数的说明。
当然还有其他方面,比如之前删除和上传没有成功,但是状态码返回200,经过与够快的开发人员一番沟通,发现了这两个api的缺陷,现在已经完善了,不会再遇到。
通过对够快网盘的支持,我也进一步学习了iOS的网络编程,收获还是很多的。
iOS-ASIHTTPRequest框架学习的更多相关文章
- iOS学习——iOS 整体框架及类继承框架图
整理自:IOS 整体框架类图值得收藏 一 整体框架 在iOS开发过程中,对iOS的整理框架的了解和学习是必不可少的一个环节,今天我们就好好来了解一下iOS的整体框架.首先贴一个关于iOS的框架介绍:i ...
- iOS网络编程--ASIHTTPRequest框架安装和配置-图文解说
ASIHTTPRequest框架是优秀的第三方Objective-C的HTTP框架,支持Mac OS X和iOS下的HTTP开发.技术支持网站是http://allseeing-i.com/ASIHT ...
- iOS网络编程-ASIHTTPRequest框架同步请求-备用
在ASIHTTPRequest框架中与HTTP请求相关的类有:ASIHTTPRequest和ASIFormDataRequest,其中最常用的是ASIHTTPRequest,ASIFormDataRe ...
- 够快网盘支持与iOS-ASIHTTPRequest框架学习
够快网盘支持与iOS-ASIHTTPRequest框架学习 前段时间在公司的产品中支持了够快网盘,用于云盘存储. 在这个过程中,学习到了很多新的知识,也遇到了很多问题,在此记录一下. 首先就够快的AP ...
- 移动开发iOS&Android对比学习--异步处理
在移动开发里很多时候需要用到异步处理.Android的主线程如果等待超过一定时间的时候直接出现ANR(对不熟悉Android的朋友这里需要解释一下什么叫ANR.ANR就是Application Not ...
- 关于iOS开发的学习
关于iOS开发的学习,打个比方就像把汽车分解: 最底层的原料有塑料,钢铁 再用这些底层的东西造出来发动机,座椅 最后再加上写螺丝,胶水等,把汽车就拼起来了 iOS基本都是英文的资料, ...
- ASIHTTPRequest框架使用总结系列之阿堂教程2(同步请求)
从本篇开始,阿堂结合一些具体代码来说明.在ASIHTTPRequest框架中,与http请求相关的类有ASIHTTPRequest 和 ASIFormDataRequest,其中最常用的是 ASIH ...
- ASIHTTPRequest框架使用总结系列之阿堂教程1(安装配置篇
在前年,阿堂在<IOS开发系列之阿堂教程:玩转IPhone客户端和Web服务端交互(客户端)实践>一文中,对于ASIHTTPRequest框架有过一些介简单绍,具体链接地址见http:// ...
- ASIHTTPRequest简单学习
ASIHTTPRequest框架是优秀的第三方Objective-C的HTTP框架,支持Mac OS X和iOS下的HTTP开发. 一.ASIHTTPRequest框架的安装和配置 (1)首先要在项目 ...
随机推荐
- HBase集群的安装部署
HBase的安装是是建立在hadoop和zookeeper集群之上的 安装的步骤跟伪分布式差不多,只是修改了一些配置文件 解压缩.重命名.设置环境变量 把hbase-0.94.2-security.t ...
- IReferenceCounted DotNetty.Common
// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file ...
- 倍福TwinCAT(贝福Beckhoff)应用教程13.3 TwinCAT控制松下伺服 NC配合完整上位
这是TwinCAT教程的最后一节,简单讲述了以C#为上位,通过ADS控制TwinCAT下位,实现完整控制两轴模组的功能.可以发现,在上位层已经没有了运动控制的代码,不管是要执行哪种运动,无非是把目标参 ...
- javaSE中的输入输出流---一个读取流,相应多个输出流。并且生成的碎片文件都有有序的编号
<span style="font-size:18px;">package com.io.other.split; import java.io.File; impor ...
- Unity3D研究院之IOS本地消息通知LocalNotification的使用(六十七)
http://www.xuanyusong.com/archives/2632 现在的游戏里一般都会有本地消息,比如每天定时12点或者下午6点告诉玩家进入游戏领取体力.这种东西没必要服务器去推送 ...
- Apache 配置:是否显示文件列表
Apache 配置:是否显示文件列表 进入虚拟主机配置文件 显示文件列表的话 options Indexes FollowSymLinks 不显示文件列表的话 options FollowSymLin ...
- Data truncation: Data too long for column
是字符集问题引起的,用show full fields from + 表名就可以看出你的列的编码格式把它改成GBK或者GB2312.uTF-8.如果还不行的话,把你表的编码格式也改成上面的编码格式,我 ...
- CoolHash数据库引擎压测对比报告
Coolhash 当前性能指标:读写吞吐量超过百万,千万级别查询1秒完成,连续48小时打满CPU强压力运行稳定.redis官方公布读写性能在10万 tps,leveldb官方公布写性能在40万tps, ...
- 实现乐鑫esp8266的无线OTA升级,实现远程在线升级固件
代码地址如下:http://www.demodashi.com/demo/12994.html 一.前言: 写了这么多的8266博文,一直以满意100%的心态去敲写代码固件烧录,以致很少出现 bug ...
- svn上检出的项目在myeclipse中报错的解决
项目本身应该是没问题的,应该是验证方面导致的错误的报错,取消验证即可:右键项目,如下操作: 除此之外,还应考虑是否环境问题引起的报错,比如:项目jar包是否发布,jdk的版本,tomcat的版本,等等