2014-04-21 107 views
2

我正在使用AFHTTPSessionManager子類通過webservices下載和上傳數據。除了upoload進度視圖,一切似乎都正常,我正在使用UIProgressView + AFNetworking類別。
代碼設置這樣的:
AFNetworking 2.0 + UIProgressView如何正確顯示上傳會話的進度

NSURLSessionTask * task = [[AFHTTPSharedClient sharedHTTPClient] addMediaWithURI:self.filePath success:^(NSURLSessionDataTask *task, BOOL added) { 
     if (added) { 
      NSLog(@"Operation succ"); 
     } 
     weakSelf.progressContainerView.hidden = YES; 
    } orFailure:^(NSURLSessionDataTask *task, NSError *error) { 
     weakSelf.progressContainerView.hidden = YES; 
    }]; 
    self.progressContainerView.hidden = NO; 
    [self.uploadProgressView setProgressWithUploadProgressOfTask:(NSURLSessionUploadTask*)task animated:YES]; 


這一方法是直接調用:

session = [self POST:ApiPostURL parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { 
      [formData appendPartWithFileURL:[NSURL fileURLWithPath:mediaURI] name: ParameterMultimedia error:appendError]; 
     } success:^(NSURLSessionDataTask *task, id responseObject) { 
      NSLog(@"%@", responseObject); 
      if ([responseObject[@"status"] isEqualToString:@"ko"]) { 
       NSError * error = [NSError errorWithDomain:@"it.share.auth" code:500 userInfo:nil]; 
       failure(task, error); 
       return ; 
      } 
      success (task, YES); 
     } failure:^(NSURLSessionDataTask *task, NSError *error) { 
      NSLog(@"%@", error); 
      failure(task, error); 
     }]; 

一旦附上進度視圖,如果我在它的方法我可以本身是正確觀察檢查任務進度方法:

​​3210

問題是if ([object countOfBytesExpectedToSend] > 0)永遠是假的,因爲countOfBytesExpectedToSend是0,讀取DOC約NSURLSession蘋果表示:

討論的網址加載系統能夠確定三種方式 上傳數據的長度:

從長度作爲上傳主體提供的NSData對象。從 上載任務(不是下載任務)的 的上傳主體提供的磁盤上的文件的長度。從 請求對象的內容長度,如果明確設置

如果我從請求打印值要求頭Content-Leght我得到一個有效值:

"Accept-Language" = "it;q=1, en;q=0.9, fr;q=0.8, de;q=0.7, ja;q=0.6, nl;q=0.5"; 
"Content-Length" = 232172; 
"Content-Type" = "multipart/form-data; boundary=Boundary+357828FACC07BFAC"; 
"User-Agent" = "XXXXX/1.0 (iPad; iOS 7.1; Scale/1.00)"; 

我可以」 t得到爲什麼總是返回一個值等於0.

回答

2

Googleing,githubbing,我找到了答案,本質上這是NSURLSession的一個「功能」,當你創建一個上傳會話任務接管你的設置標題。由於在一個流中沒有真正的內容大小,如果我們設置了任務將重寫它的內容。
幸好NSURLSession有兩個請求屬性currentRequest(被覆蓋的一個)和originalRequest。原始請求將繼續保持我們的Content-Length
我對UIProgressView + AFNetworking類別做了幾個mod,使它能夠使用設定的內容長度工作,最好再檢查一下是否有一個流。

- (void)observeValueForKeyPath:(NSString *)keyPath 
         ofObject:(id)object 
         change:(__unused NSDictionary *)change 
         context:(void *)context 
{ 
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 
    if (context == AFTaskCountOfBytesSentContext || context == AFTaskCountOfBytesReceivedContext) { 
     if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesSent))]) { 

      //upload content length issue 
//   if ([object countOfBytesExpectedToSend] > 0) { 
      NSInteger byteToSend = [[[object originalRequest] valueForHTTPHeaderField:@"Content-Length"] integerValue]; 
      if (byteToSend){ 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        [self setProgress:[object countOfBytesSent]/(byteToSend * 1.0f) animated:self.af_uploadProgressAnimated]; 
//     [self setProgress:[object countOfBytesSent]/([object countOfBytesExpectedToSend] * 1.0f) animated:self.af_uploadProgressAnimated]; 
       }); 
      } 
     } 

     if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesReceived))]) { 
      if ([object countOfBytesExpectedToReceive] > 0) { 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        [self setProgress:[object countOfBytesReceived]/([object countOfBytesExpectedToReceive] * 1.0f) animated:self.af_downloadProgressAnimated]; 
       }); 
      } 
     } 

     if ([keyPath isEqualToString:NSStringFromSelector(@selector(state))]) { 
      if ([(NSURLSessionTask *)object state] == NSURLSessionTaskStateCompleted) { 
       @try { 
        [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(state))]; 

        if (context == AFTaskCountOfBytesSentContext) { 
         [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesSent))]; 
        } 

        if (context == AFTaskCountOfBytesReceivedContext) { 
         [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesReceived))]; 
        } 
       } 
       @catch (NSException * __unused exception) {} 
      } 
     } 
    } 
#endif 
} 
+0

它的工作原理...但不是很好的變化,你已經報告@mattt? (AFNetworking) – silvaric

+0

我做了你可以看到這裏https://github.com/AFNetworking/AFNetworking/issues/1398和https://github.com/AFNetworking/AFNetworking/issues/1354。馬特已回覆說他不支持這種模式。 – Andrea

+1

並且在這裏https://github.com/AFNetworking/AFNetworking/issues/2027。我完全理解Mattt點,因爲對於AFNetworking的所有測試單元來說,這是一個真正未經測試的mod。我可以告訴你,我在6個月左右成功使用它。 – Andrea