使用AFNetworking 2.0上传进度

时间:2014-06-17 11:22:23

标签: ios objective-c

我知道这个问题在本网站上非常流行,但在搜索了大部分答案之后,我找不到解决方案。 我的应用是将图像上传到远程网址。我尝试了几种上传方式,并且所有方法都成功了:
(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或阻止)。

3 个答案:

答案 0 :(得分: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 ;\

答案 1 :(得分:0)

在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来计算它。

答案 2 :(得分:0)

最后,我发现了没有调用进度块的原因:我已经上传了一张大约几十Kb的非常小的图像。我尝试上传更大的文件并调用进度块。根据我的经验,KVO与NSProgress并不起作用。而不是那样,我们可以使用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); }