够快网盘支持与iOS-ASIHTTPRequest框架学习
够快网盘支持与iOS-ASIHTTPRequest框架学习
前段时间在公司的产品中支持了够快网盘,用于云盘存储。
在这个过程中,学习到了很多新的知识,也遇到了很多问题,在此记录一下。
首先就够快的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:] intValue] >= ) {
[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框架学习的更多相关文章
- 《Python Web开发学习实录》高清PDF版|百度网盘免费下载|Python Web开发学习实录
<Python Web开发学习实录>高清PDF版|百度网盘免费下载|Python Web开发学习实录 提取码:9w3o 内容简介 Python是目前流行的动态脚本语言之一. 李勇,本书共1 ...
- Python网络编程基础|百度网盘免费下载|零基础入门学习资料
百度网盘免费下载:Python网络编程基础|零基础学习资料 提取码:k7a1 目录: 第1部分 底层网络 第1章 客户/服务器网络介绍 第2章 网络客户端 第3章 网络服务器 第4章 域名系统 第5章 ...
- Python编程入门(第3版)|百度网盘免费下载|零基础入门学习资料
百度网盘免费下载:Python编程入门(第3版) 提取码:rsd7 目录 · · · · · · 第1章 编程简介 11.1 Python语言 21.2 Python适合用于做什么 31.3 程序员 ...
- mac百度网盘破解版
以下资源来源于网络收集分享,如有问题请联系我删除!来源入口,后面链接挂了,可去原网址访问! 还在为Mac百度网盘下载速度慢而烦恼吗?百度云盘又是一个非常实用的分享工具,可支持图片.视频.音乐.文档.种 ...
- 关于Pandownload和百度网盘
本周,百度网盘第三方客户端 Pandownload 被查,开发者被“跨省追捕”:百度网盘“用户激励计划”在未充分告知用户的情况下,利用用户自己的电脑做 P2P 上传节点.这两件事再度引发了对百度网盘的 ...
- iOS网络编程--ASIHTTPRequest框架安装和配置-图文解说
ASIHTTPRequest框架是优秀的第三方Objective-C的HTTP框架,支持Mac OS X和iOS下的HTTP开发.技术支持网站是http://allseeing-i.com/ASIHT ...
- 【推荐网站】下载国外网盘+强大的离线下载站—offcloud.com
博主在网上浏览时看到一篇帖子,推荐了一个离线下载网站–offcloud.com,支持上传种子文件.磁力链和几十家网盘的直连下载,厉害了我的哥,这是个啥网站这么666.即使之前咱们写了几篇文章来自建下载 ...
- 和付费网盘说再见,跟着本文自己起个网盘(Java 开源项目)
本文适合有 Java 基础知识的人群,跟着本文可学习和运行 Java 网盘项目. 本文作者:HelloGitHub-秦人 HelloGitHub 推出的<讲解开源项目>系列. 今天给大家带 ...
- vfd-cloud——一个适合练习上手的云存储网盘springboot项目(开发中)
vfd-cloud 一个基于SpringBoot的云存储网盘项目,适合练手学习SpringBoot,用到的技术栈列到了下面.支持用户的注册登陆及修改密码,利用邮箱进行验证.支持 ...
随机推荐
- VC中MessageBox的常见用法
一.关于MessageBox 消息框是个很常用的控件,属性比较多,本文列出了它的一些常用方法,及指出了它的一些应用场合. 1.MessageBox("这是一个最简单的 ...
- js 正则学习小记之左最长规则
原文:js 正则学习小记之左最长规则 昨天我在判断正则引擎用到的方法是用 /nfa|nfa not/ 去匹配 "nfa not",得到的结果是 'nfa'.其实我们的本意是想得到整 ...
- Ruby入门--Linux/Windows下的安装、代码开发及Rails实战
Ruby入门--Linux/Windows下的安装.代码开发及Rails实战 http://www.linuxidc.com/Linux/2014-04/100242.htm Ubuntu 13.04 ...
- Linux svnserver存储路径和文件的详细解释
svn有两种存储方式:BDB和FSFS,眼下用的最多的是FSFS方式,这样的方式的话.通常是存储在\db\revs目录下,里面有一堆以版本命名的文件.如:0.1.2.3.4......,那个就是了 比 ...
- windows phone8.1:Xml,Json序列化和反序列化
原文:windows phone8.1:Xml,Json序列化和反序列化 小梦本例主要实现以下四点内容: 将Car对象序列化为xml 将Car对象序列化为Json 将xml反序列化为Car对象 将js ...
- Objective-C中的Category(分类)
Objective-C中的Category(分类) 1 Category概念:动态的为已经存在的类加入新的行为(方法) 2 Category(分类)创建的方法 (1)通过Xcode生成分类 (2)能够 ...
- 深入理解C指针之五:指针和字符串
原文:深入理解C指针之五:指针和字符串 基础概念 字符串可以分配到内存的不同区域,通常使用指针来支持字符串操作.字符串是以ASCII字符NUL结尾的字符序列.ASCII字符NUL表示为\0.字符串通常 ...
- gnu 扩展之#和##
转自:http://chongsoft.bokee.com/5816474.html 今天测试了宏定义中的 "#" 和 "##" 的区别. 结果如下: &quo ...
- SQL语句分享[不定期更新]
查询临时表 if object_id('')>0 查询表中的数据 select 'insert into ta1(col1,col2,col3) values('''+ltrim(列1)+''' ...
- phpstorm集成phpunit
1.下载phpunit.phar,将该文件放到某个工程中 2.File > Settings > Languages & Frameworks > PHP > PHPU ...