123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- //
- // QNFormUpload.m
- // QiniuSDK
- //
- // Created by bailong on 15/1/4.
- // Copyright (c) 2015年 Qiniu. All rights reserved.
- //
- #import "QNFormUpload.h"
- @interface QNFormUpload ()
- @property (nonatomic, strong) NSData *data;
- @property (nonatomic) int retryTimes;
- @property (nonatomic, strong) NSString *fileName;
- @property (nonatomic) float previousPercent;
- @end
- @implementation QNFormUpload
- - (instancetype)initWithData:(NSData *)data
- withKey:(NSString *)key
- withFileName:(NSString *)fileName
- withToken:(QNUpToken *)token
- withIdentifier:(NSString *)identifier
- withCompletionHandler:(QNUpCompletionHandler)block
- withOption:(QNUploadOption *)option
- withSessionManager:(QNSessionManager *)sessionManager
- withConfiguration:(QNConfiguration *)config {
- if (self = [super init]) {
- self.data = data;
- self.size = (UInt32)data.length;
- self.key = key;
- self.token = token;
- self.option = option != nil ? option : [QNUploadOption defaultOptions];
- self.complete = block;
- self.sessionManager = sessionManager;
- self.config = config;
- self.fileName = fileName != nil ? fileName : @"?";
- self.previousPercent = 0;
- self.access = token.access;
- self.currentZoneType = QNZoneInfoTypeMain;
- self.identifier = identifier;
- self.requestType = QNRequestType_form;
- }
- return self;
- }
- - (void)put {
-
- NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
- if (self.key) {
- parameters[@"key"] = self.key;
- }
- parameters[@"token"] = self.token.token;
- [parameters addEntriesFromDictionary:self.option.params];
- parameters[@"crc32"] = [NSString stringWithFormat:@"%u", (unsigned int)[QNCrc32 data:_data]];
-
- [self nextTask:0 needDelay:NO host:[self.config.zone up:self.token zoneInfoType:self.currentZoneType isHttps:self.config.useHttps frozenDomain:nil] param:parameters];
- }
- - (void)nextTask:(int)retried needDelay:(BOOL)needDelay host:(NSString *)host param:(NSDictionary *)param {
-
- if (needDelay) {
- QNAsyncRunAfter(self.config.retryInterval, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- [self nextTask:retried host:host param:param];
- });
- } else {
- [self nextTask:retried host:host param:param];
- }
- }
- - (void)nextTask:(int)retried host:(NSString *)host param:(NSDictionary *)param {
-
- if (self.option.cancellationSignal()) {
- [self collectUploadQualityInfo];
- QNResponseInfo *info = [Collector userCancel:self.identifier];
- self.complete(info, self.key, nil);
- return;
- }
-
- QNInternalProgressBlock p = ^(long long totalBytesWritten, long long totalBytesExpectedToWrite) {
- float percent = (float)totalBytesWritten / (float)totalBytesExpectedToWrite;
- if (percent > 0.95) {
- percent = 0.95;
- }
- if (percent > self.previousPercent) {
- self.previousPercent = percent;
- } else {
- percent = self.previousPercent;
- }
- self.option.progressHandler(self.key, percent);
- };
- QNCompleteBlock complete = ^(QNHttpResponseInfo *httpResponseInfo, NSDictionary *respBody) {
- [self collectHttpResponseInfo:httpResponseInfo fileOffset:QN_IntNotSet];
-
- if (httpResponseInfo.isOK) {
- self.option.progressHandler(self.key, 1.0);
- [self collectUploadQualityInfo];
- QNResponseInfo *info = [Collector completeWithHttpResponseInfo:httpResponseInfo identifier:self.identifier];
- self.complete(info, self.key, respBody);
- } else if (httpResponseInfo.couldRetry) {
- if (retried < self.config.retryMax) {
- [self nextTask:retried + 1 needDelay:YES host:host param:param];
- } else {
- if (self.config.allowBackupHost) {
- NSString *nextHost = [self.config.zone up:self.token zoneInfoType:self.currentZoneType isHttps:self.config.useHttps frozenDomain:host];
- if (nextHost) {
- [self nextTask:0 needDelay:YES host:nextHost param:param];
- } else {
- QNZonesInfo *zonesInfo = [self.config.zone getZonesInfoWithToken:self.token];
- if (self.currentZoneType == QNZoneInfoTypeMain && zonesInfo.hasBackupZone) {
- self.currentZoneType = QNZoneInfoTypeBackup;
- [self nextTask:0 needDelay:YES host:[self.config.zone up:self.token zoneInfoType:self.currentZoneType isHttps:self.config.useHttps frozenDomain:nil] param:param];
- } else {
- [self collectUploadQualityInfo];
- QNResponseInfo *info = [Collector completeWithHttpResponseInfo:httpResponseInfo identifier:self.identifier];
- self.complete(info, self.key, respBody);
- }
- }
- } else {
- [self collectUploadQualityInfo];
- QNResponseInfo *info = [Collector completeWithHttpResponseInfo:httpResponseInfo identifier:self.identifier];
- self.complete(info, self.key, respBody);
- }
- }
- } else {
- [self collectUploadQualityInfo];
- QNResponseInfo *info = [Collector completeWithHttpResponseInfo:httpResponseInfo identifier:self.identifier];
- self.complete(info, self.key, respBody);
- }
- };
- [self.sessionManager multipartPost:host
- withData:self.data
- withParams:param
- withFileName:self.fileName
- withMimeType:self.option.mimeType
- withIdentifier:self.identifier
- withCompleteBlock:complete
- withProgressBlock:p
- withCancelBlock:self.option.cancellationSignal
- withAccess:self.access];
- }
- @end
|