使用AFNetworking 2.0进行流请求时,我遇到了几个挑战。
我想要上传大量文件(约50MB)到服务器,并且请求必须是流式的。(否则应用程序将因为内存压力而崩溃)
我已经尝试了各种方法在AFNetworking 2.0中实现,但都没有成功。 目前我正在使用以下方式:
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:baseServiceUrl parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
int imageIndex = 0;
for (NSURL *tempFileUrl in tempFilesUrlList) {
NSString* fileName = [NSString stringWithFormat:@"image%d", imageIndex];
NSError *appendError = nil;
[formData appendPartWithFileURL:tempFileUrl name:fileName error:&appendError];
imageIndex++;
}
} error:&error];
AFHTTPRequestOperation *requestOperation = nil;
requestOperation = [manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
DLog(@"Uploading files completed: %@\n %@", operation, responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
DLog(@"Error: %@", error);
}];
[requestOperation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
double percentDone = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
DLog(@"progress updated(percentDone) : %f", percentDone);
}];
[requestOperation start];
这个代码可以正常工作,但它并不是流式的。它在内存中准备请求,如果请求过大就会崩溃。我曾尝试使用本机套接字和流的方法,但苹果公司表示可能因此拒绝应用程序。
我尝试了另一种方法:
AFHTTPSessionManager* manager = [AFHTTPSessionManager manager];
NSString *appID = [[NSBundle mainBundle] bundleIdentifier];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:appID];
NSURL* serviceUrl = [NSURL URLWithString:baseServiceUrl];
manager = [manager initWithBaseURL:serviceUrl sessionConfiguration:configuration];
NSURLSessionDataTask *uploadFilesTask = [manager POST:baseServiceUrl parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
int imageIndex = 0;
for (NSURL *tempFileUrl in tempFilesUrlList) {
NSString* fileName = [NSString stringWithFormat:@"image%d", imageIndex];
NSError *appendError = nil;
[formData appendPartWithFileURL:tempFileUrl name:fileName error:&appendError];
imageIndex++;
}
} success:^(NSURLSessionDataTask *task, id responseObject) {
DLog(@"Files uploaded successfully: %@\n %@", task, responseObject);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
DLog(@"Error: %@", error);
}];
[progressBar setProgressWithUploadProgressOfTask:uploadFilesTask animated:true];
但是这给我带来了运行时错误,显示:
终止应用程序,原因:未捕获的异常'NSGenericException', 原因:后台会话中的上传任务必须来自文件 *** 第一次抛出调用堆栈:( 0 CoreFoundation 0x02cc75e4 __exceptionPreprocess + 180 1 libobjc.A.dylib
0x02a4a8b6 objc_exception_throw + 44 2 CFNetwork
0x0459eb6c -[__NSCFBackgroundSessionBridge uploadTaskForRequest:uploadFile:bodyData:completion:] + 994 3
CFNetwork 0x045f2f37 -[__NSCFURLSession uploadTaskWithStreamedRequest:] + 73
(必须进行流式传输,并能够在后台继续)