我正在使用 AFHTTPSessionManager 子类通过网络服务下载和上传数据。除了上传进度 View 之外,一切似乎都运行良好,我使用的是 UIProgressView+AFNetworking 类别。
代码是这样设置的:
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 setProgressWithUploadProgressOfTaskNSURLSessionUploadTask*)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);
}];
一旦我附加了进度 View ,如果我 checkin 它的方法,我可以确定它正确地观察了方法中的任务进度:
- (void)observeValueForKeyPathNSString *)keyPath
ofObjectid)object
change__unused NSDictionary *)change
contextvoid *)context <br>
问题是 if ([object countOfBytesExpectedToSend] > 0) 总是 false 因为 countOfBytesExpectedToSend 为 0,阅读有关 NSURLSession 的文档苹果表示:
Discussion The URL loading system can determine the length of the
upload data in three ways:
From the length of the NSData object provided as the upload body. From
the length of the file on disk provided as the upload body of an
upload task (not a download task). From the Content-Length in the
request object, if you explicitly set it
如果我从请求 header 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)";
我不明白为什么总是返回等于 0 的值。
Best Answer-推荐答案 strong>
Googleing,githubbing,我找到了答案,本质上这是 NSURLSession 的“功能”,当您使用 uploadstream 创建 session 时,任务会接管您设置的标题。由于在流中没有真正的内容大小,如果我们设置一些东西,任务将重写它。
幸运的是 NSURLSession 有两个请求属性 currentRequest (被覆盖的)和 originalRequest 。原始请求将继续保留我们的 Content-Length 。
我对 UIProgressView+AFNetworking 类别做了一些修改,以使其使用设置的内容长度工作,最好再检查一下是否有流。
- (void)observeValueForKeyPathNSString *)keyPath
ofObjectid)object
change__unused NSDictionary *)change
contextvoid *)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
}
关于ios - AFNetworking 2.0 + UIProgressView 如何正确显示上传 session 的进度,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/23193983/
|