【问题标题】:Upload progress with AFNetworking 2.0使用 AFNetworking 2.0 上传进度
【发布时间】:2014-06-17 11:22:23
【问题描述】:

我知道这个问题在这个网站上很受欢迎,但是在搜索了大部分答案后,我找不到解决方案。 我的应用程序是将图像上传到远程 url。我尝试了几种上传方式,都成功了:
(1) 使用 AFURLSessionManager

AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[(AFHTTPResponseSerializer*)manager.responseSerializer setAcceptableContentTypes:[NSSet setWithObjects:@"multipart/form-data", nil]];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
    if (error) {
        NSDictionary *userInfo=[error userInfo];
        id responseError=[userInfo objectForKey:@"AFNetworkingOperationFailingURLResponseErrorKey"];
        if ([responseError isKindOfClass:[NSHTTPURLResponse class]]) {
            NSHTTPURLResponse *reponse=(NSHTTPURLResponse*)responseError;
            if (reponse.statusCode==200) {
                result(YES);
            } else {
                result(NO);
            }
        } else {
            result(NO);
        }
    } else {
        result(YES);
    }
}];
[uploadTask resume];

为此,我使用 KVO 来监控进度,但没有运气。

(2) 使用AFHTTPRequestOperation

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    [operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
        NSLog(@"total bytes written: %lld",totalBytesWritten);
    }];
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        result(YES);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        if (operation.response.statusCode==200) {
            result(YES);
        } else {
            result(NO);
        }
    }];
    [operation start];

仅在开始上传时立即显示日志“写入的总字节数:”一次,文件体积为 100%。

(3) 使用 AFHTTPRequestOperationManager

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    AFHTTPRequestOperation *operation =
    [manager HTTPRequestOperationWithRequest:request
                                     success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                         NSLog(@"Success %@", responseObject);
                                         result(YES);
                                     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                         if (operation.response.statusCode==200) {
                                             result(YES);


              } else {
                                         result(NO);
                                     }
                                 }];

// 4. Set the progress block of the operation.
[operation setUploadProgressBlock:^(NSUInteger __unused bytesWritten,
                                    long long totalBytesWritten,
                                    long long totalBytesExpectedToWrite) {
    double percentDone = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
    NSLog(@"progress updated(percentDone) : %f", percentDone);
}];

// 5. Begin!
[operation start];

=> 与第二个解决方案的结果相同。

请注意,所有解决方案都已成功上传,但进度未更新(NSProgress 或阻止)。

【问题讨论】:

    标签: ios objective-c


    【解决方案1】:
    NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"<your upload url>" parameters:@{<parameters dict> } constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
             _STRONGREF(strongSelf);
    
                NSString  *name=@"file_data_name";
                [formData appendPartWithFileURL:[NSURL fileURLWithPath:path] name:name fileName:<file Path> mimeType:@"image/png" error:nil];//u can use data as well with other method
            }
    
        } error:nil];
        [request setTimeoutInterval:180];
        [request setValue:@"VAlue_your" forHTTPHeaderField:@"feild"];//set headers
        AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
        NSProgress *progress = nil;
        NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
            if (error) {
                NSLog(@"Error: %@", error);
            } else {
                NSLog(@"%@ %@", response, responseObject);
            }
        }];
    
        NSLog(@"%@",progress);
        [uploadTask resume];
    

    我的宏是

    #define  _WEAKREF(obj)         __weak typeof(obj)ref=obj;
    #define  _STRONGREF(name)      __strong typeof(ref)name=ref;\
                                   if(!name)return ;\
    

    【讨论】:

      【解决方案2】:

      在你的 NSProgress 上设置一个观察者。

      类似

      [uploadTask resume];
      [progress addObserver:self
                         forKeyPath:@"fractionCompleted"
                            options:NSKeyValueObservingOptionNew
                            context:NULL];
      

      然后执行

      - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
      {
      if ([keyPath isEqualToString:@"fractionCompleted"]) {
          NSProgress *progress = (NSProgress *)object;
          NSLog(@"progress = %f", progress.fractionCompleted);
      
      } else {
          [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
          }
      }
      

      上传任务完成后别忘了移除观察者。

      注意:progress.fractionCompleted 返回一个百分比值。以 MB 为单位由您决定。

      【讨论】:

      • 谢谢,但我在我的项目中使用了 bove 代码(KVO-Key 值观察器)。我不知道为什么观察者不开火。
      【解决方案3】:

      最后,我找到了没有调用进度块的原因:我上传了一个非常小的图像,大约只有几十 Kb。我尝试上传更大尺寸的文件并调用进度块。根据我的经验,带有 NSProgress 的 KVO 不起作用。取而代之的是,我们可以使用 AFHTTPRequestOperation 或 AFHTTPRequestOperationManager。如果您喜欢手动上传,您可以使用How can I upload a photo to a server with the iPhone? 建议的 NSURLConnection 以及委托方法:
      - (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite { NSLog(@"percent: %d",100*totalBytesWritten/totalBytesExpectedToWrite); }

      【讨论】:

      • 我按照您的建议上传了一个更大的文件,并且正在调用委托连接:didSendBodyData 也打印了日志。但是 1) 委托中的 self.uploadProgress 为 nil,因此未调用回调块 setUploadProgressBlock。 2) AFURLConnectionOperation.m 中的调试描述了 self.uploadProgress 的内容,而 setUploadProgressBlock 在委托中变为 nil。
      猜你喜欢
      • 2023-03-31
      • 2013-11-19
      • 2014-01-06
      • 1970-01-01
      • 1970-01-01
      • 2014-04-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多