版本記錄
版本號(hào) | 時(shí)間 |
---|---|
V1.0 | 2017.04.20 |
前言
最近正在做一個(gè)項(xiàng)目撒璧,要用到七牛的云存儲(chǔ)服務(wù)哥遮,例如注冊(cè)賬號(hào)的時(shí)候需要上傳注冊(cè)者的頭像,這個(gè)時(shí)候我們主要就是將圖像上傳到七牛服務(wù)器美澳,服務(wù)器吐給我們一個(gè)URL销部,然后我們將圖片的URL傳給服務(wù)器摸航,服務(wù)器存儲(chǔ)的就是這個(gè)圖片的外接URL地址。
??下面是兩個(gè)鏈接:
??七牛官方文檔
??七牛github地址
七牛SDK概覽
這里我就以上傳圖片為例子進(jìn)行說明七牛服務(wù)器上傳服務(wù)的原理舅桩。至于視頻音頻等的原理都類似酱虎。七牛可以從cocoapods上獲取和集成擂涛。我們先看一下七牛主要的框架文件读串。
這里上傳主要就是采用QNUploadManager這個(gè)類。
七牛SDK詳述
SDK環(huán)境適配
七湃雎瑁現(xiàn)在已經(jīng)更新到7.1版本恢暖,他依賴于AFNetworking框架,對(duì)ios系統(tǒng)和xcode版本也有要求狰右。需要一定的搭配杰捂,具體如下。
|SDK版本|最低ios版本|最低OSX版本|Xcode版本|
|:----:|:----:|:----:|:----:|:---:|
|7.1/AFN-3.x|ios7|OS X10.9|xoode 6|
|7.0/AFN-2.x|ios6|OS X10.8|xoode 5|
|7.x/AFN-1.x|ios5|OS X10.7|xoode 5|
|6.x/AFN-1.x|ios6|None|xoode 5|
我們先看一下上傳文件的實(shí)例代碼挟阻。
#import <QiniuSDK.h>
...
NSString *token = @"從服務(wù)端SDK獲取";
QNUploadManager *upManager = [[QNUploadManager alloc] init];
NSData *data = [@"Hello, World!" dataUsingEncoding : NSUTF8StringEncoding];
[upManager putData:data key:@"hello" token:token
complete: ^(QNResponseInfo *info, NSString *key, NSDictionary *resp) {
NSLog(@"%@", info);
NSLog(@"%@", resp);
} option:nil];
...
//注意:key 及所有需要輸入的字符串必須采用 utf8 編碼琼娘,如果使用非 utf8 編碼訪問七牛云存儲(chǔ)將反饋錯(cuò)誤。
SDK幾個(gè)重要參數(shù)
1.option參數(shù)
關(guān)于 option 參數(shù)附鸽,一般情況下脱拼,開發(fā)者可以忽略 put 方法中的 option 參數(shù),即在調(diào)用時(shí)保持 option 的值為 nil 即可坷备。但對(duì)于一些特殊的場(chǎng)景熄浓,我們可以給 option 傳入一些高級(jí)選項(xiàng)以更精確的控制上傳行為和獲取進(jìn)度信息。option QNUploadOption 類型包含的變量有:params省撑、mimeType赌蔑、checkCrc、progressHandler竟秫、cancelSignal娃惯。
2.param參數(shù)
用戶自定義參數(shù),必須以 x:開頭肥败,這些參數(shù)可以作為變量用于 upToken 的 callbackBody趾浅、returnBody、asyncOps 參數(shù)中馒稍,具體信息請(qǐng)參閱自定義變量皿哨。 一個(gè)簡(jiǎn)單的例子如下:
QNUploadOption *opt = [[QNUploadOption alloc] initWithMime:@"text/plain" progressHandler:nil params:@{ @"x:foo":@"fooval" } checkCrc:YES cancellationSignal:nil];
[upManager putData:data key:@"hello" token:token
complete: ^(QNResponseInfo *info, NSString *key, NSDictionary *resp) {
NSLog(@"%@", info);
NSLog(@"%@", resp);
} option:opt];
3.mineType參數(shù)
為上傳文件設(shè)置一個(gè)自定義的 MIME 類型,如果為空纽谒,那么服務(wù)端自動(dòng)檢測(cè)文件的 MIME 類型证膨。
4. checkCrc參數(shù)
checkCrc 為 NO 時(shí),服務(wù)端不會(huì)校驗(yàn) crc32 值鼓黔,checkCrc 為 YES 時(shí)央勒,服務(wù)端會(huì)計(jì)算上傳文件的 crc32 值不见,然后與用戶提供的 crc32 參數(shù)值比較確認(rèn)文件的完整性,如果校驗(yàn)失敗會(huì)返回 406 錯(cuò)誤订歪。
5. 上傳進(jìn)度監(jiān)測(cè)和取消上傳
這里利用的就是block來獲得上傳進(jìn)度和取消上傳脖祈。
上傳的block為
typedef void (^QNUpProgressHandler)(NSString *key, float percent);
如果實(shí)現(xiàn)了這個(gè) block肆捕,并作為 option 參數(shù)傳入刷晋,會(huì)及時(shí)得到上傳進(jìn)度通知。
取消上傳的block為
typedef BOOL (^QNUpCancellationSignal)(void);
如果希望中途可以取消上傳慎陵,需要實(shí)現(xiàn)上面的 block眼虱,并作為參數(shù)傳入 option。
6. 斷點(diǎn)續(xù)傳
SDK 實(shí)現(xiàn)了斷點(diǎn)續(xù)上傳席纽,如果需要保存上傳進(jìn)度捏悬,需要您在生成 UploaderManager 實(shí)例時(shí)傳入一個(gè)實(shí)現(xiàn)保存進(jìn)度的代理,SDK 自帶了將進(jìn)度保存進(jìn)文件的方法润梯,您可以自己實(shí)現(xiàn)其他保存方式过牙。
NSError *error;
QNFileRecorder *file = [QNFileRecorder fileRecorderWithFolder:@"保存目錄" error:&error];
//check error
QNUploadManager *upManager = [[QNUploadManager alloc] initWithRecorder:file];
SDK實(shí)際使用
我舉一個(gè)例子說明使用七牛的情況吧,在修改個(gè)人資料的時(shí)候纺铭,需要用戶上傳自己的頭像寇钉,上傳頭像可以使用七牛的云存儲(chǔ)。具體步驟為:
- 客戶端和服務(wù)端分別集成SDk舶赔;
- 向自己的后臺(tái)服務(wù)器發(fā)送請(qǐng)求扫倡,獲取uploadToken;
- 對(duì)接uploadManager類進(jìn)行上傳,這里有好幾個(gè)方法可以使用竟纳,需要我們傳遞uploadToken和key撵溃,其中key可以自己隨便指定一個(gè)字符串,也可以傳nil锥累,傳遞nil則七牛自動(dòng)為我們生成缘挑。
下面我就直接上大體上的代碼了。
1. 打開本地相冊(cè)獲取圖像
#pragma mark - UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
[picker dismissViewControllerAnimated:YES completion:nil];
self.uploadImage = info[UIImagePickerControllerOriginalImage];
self.infoFillView.avatarImage = self.uploadImage;
[self getTokenFromMyServer];
}
2. 請(qǐng)求自己的服務(wù)器獲取uploadToken
//從本地服務(wù)器請(qǐng)求token
- (void)getTokenFromMyServer
{
NSMutableDictionary *dictParam = [NSMutableDictionary dictionary];
[dictParam setObject:[JJConfig myProfile].token forKey:@"token"];
[dictParam setObject:@"1" forKey:@"version"];
NSString *serverURL = [NSString stringWithFormat:@"%@%@",kDomainURL,kLoginUploadImageToMyServer];
[[JJNetWorkManager manager] requestByGetNetworkWithServerUrl:serverURL parameters:dictParam success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"%@",responseObject);
if ([[responseObject objectForKey:@"code"] integerValue] == 0) {
NSDictionary *dataDict = [responseObject objectForKey:@"data"];
self.uploadToken = [dataDict objectForKey:@"uploadToken"];
self.uploadZone = [dataDict objectForKey:@"zone"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self uploadImageToQiniu];
});
}
} error:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"%@",error);
}];
}
//調(diào)用網(wǎng)絡(luò)工具桶略,我們這次用的是get請(qǐng)求
- (void)requestNetworkWithServerUrl:(NSString * _Nonnull)serverUrl parameters:(nullable id)parameters success:(successRequestBlock)successBlock error:(errorRequestBlock)errorBlock {
self.sessionManager.requestSerializer = [AFJSONRequestSerializer serializer];
self.sessionManager.responseSerializer = [AFJSONResponseSerializer serializer];
[self.sessionManager.requestSerializer setValue:@"application/json; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[self.sessionManager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
self.sessionManager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
self.sessionManager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];
[self.sessionManager.requestSerializer setValue:[ZBConfig myProfile].token forHTTPHeaderField:@"token"];
[self.sessionManager.requestSerializer setValue:@"1" forHTTPHeaderField:@"version"];
[self.sessionManager GET:serverUrl parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
DDLogVerbose(@"\nRequest URL: %@\nResponse: \n%@",task.currentRequest.URL,responseObject);
successBlock(task,responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
DDLogError(@"\nRequest URL: %@\nErrorInfo :\n%@ \nError:%@",task.currentRequest.URL,error.localizedDescription,error);
errorBlock(task,error);
}];
}
3. 上傳圖片到七牛
//上傳圖片到七牛
- (void)uploadImageToQiniu
{
QNConfiguration *congfiguration = [QNConfiguration build:^(QNConfigurationBuilder *builder) {
builder.zone = [QNZone zone1];
}];
QNUploadManager *uploadManager = [[QNUploadManager alloc] initWithConfiguration:congfiguration];
NSData *imageData = nil;
if (UIImagePNGRepresentation(self.uploadImage) == nil) {
imageData = UIImageJPEGRepresentation(self.uploadImage, 1.0);
}
else {
imageData = UIImagePNGRepresentation(self.uploadImage);
}
[uploadManager putData:imageData key:nil token:self.uploadToken complete:^(QNResponseInfo *info, NSString *key, NSDictionary *resp) {
if (info.ok) {
NSLog(@"成功");
}
else {
NSLog(@"失敗");
}
NSLog(@"info---%@",info);
NSLog(@"key---%@",key);
NSLog(@"resp---%@",resp);
} option:nil];
}
4. 看結(jié)果
2017-04-21 20:37:01.229916 ------[3346:678850] 成功
2017-04-21 20:37:01.230149 ------3346:678850] info---<QNResponseInfo= id: F967882A-963F-4E66-91BB-2F643B386F96, ver: 7.1.5, status: 200, requestId: fGgAAMnGNhHiabcU, xlog: body:16;s.ph;s.put.tw;s.put.tr:17;s.put.tw;s.put.tr:18;s.ph;s.put.tw;s.put.tr:19;s.ph;PFDS:20;PFDS:20;PFDS:21;rs9_4.sel/not found;rdb.g/no such key;DBD/404;v4.get/Document not found;rs9_4.ins;rwro.ins:1;mc.s;RS:1;rs.put:2;rs-upload.putFile:26;UP:45, xvia: (null), host: upload-z1.qiniu.com ip: 111.206.234.140 duration: 1.298980 s time: 1492778221 error: (null)>
2017-04-21 20:37:01.230222 ------[3346:678850] key---(null)
2017-04-21 20:37:01.230333 ------[3346:678850] resp---{
hash = "FgG8rxrG-vftWFCsE-Ru04QW1j7u";
key = "FgG8rxrG-vftWFCsE-Ru04QW1j7u";
}
然后我們登錄七牛云空間查看結(jié)果
我存儲(chǔ)了好幾個(gè)都成功了语淘。
后記
七牛簡(jiǎn)單的上傳任務(wù)并不難,用戶還可以自定義配置上傳删性,比如選擇上傳的服務(wù)器亏娜,華北華南等。還有設(shè)置是否需要返回上傳進(jìn)度和取消上傳蹬挺,斷點(diǎn)續(xù)傳等维贺。這需要大家在業(yè)務(wù)中慢慢的對(duì)接。謝謝大家對(duì)我的支持巴帮。