如何使用AFNetworking在后台上传任务

9

我正在尝试使用AFNetworking上传大文件,并且在应用程序处于后台时继续上传。

我可以成功地上传文件,但是当我尝试使用后台配置时--应用程序会崩溃,并显示以下堆栈跟踪: 异常:EXC_BAD_ACCESS(code=1,address=0x8000001f)

_CFStreamSetDispatchQueue
-[__NSCFBackgroundDataTask captureStream:]
__70-[__NSCFBackgroundDataTask _onqueue_needNewBodyStream:withCompletion:]_block_invoke_2
_dispatch_call_block_and_release
_dispatch_queue_drain
_dispatch_queue_invoke
_dispatch_root_queue_drain
_dispatch_worker_thread3
_pthread_wqthread

以下是一些示例代码:

注意:当我使用[NSURLSessionConfiguration defaultSessionConfiguration]时,上传成功了,但是在应用程序处于后台时不会继续。而[NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.company.appname.uploadservice"]会导致应用程序崩溃。

NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:[uploadBundle.uploadUrl absoluteString] parameters:[uploadBundle getParameters] constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
    [formData appendPartWithFileURL:uploadBundle.fileDataUrl name:uploadBundle.fileName fileName:uploadBundle.fileName mimeType:uploadBundle.mimeType error:nil];
} error:nil];

Authentication *authentication = [Authentication getInstance];
[request addValue:authentication.token forHTTPHeaderField:@"token"];
[request addValue:authentication.authorization forHTTPHeaderField:@"Authorization"];

//NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.company.appname.uploadservice"];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

NSProgress *progress = nil;
_currentUploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
    if (error) {
        NSLog(@"Error: %@", error);
    } else {
        NSLog(@"%@ %@", response, responseObject);
    }
}];

1
嘿,你找到任何解决方案了吗?我也遇到了同样的问题。请帮帮我。 - Ekta Padaliya
2个回答

8

我希望自己的回答能帮助到一些人。

我没有在任何地方找到这个文档,但是当使用后台会话配置时,似乎必须使用uploadTaskWithRequest:fromFile:progress:completionHandler:

这是一个简单的例子:

AppDelegate *appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];

id config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.opentext.core.uploadservice"];
id session = [NSURLSession sessionWithConfiguration:config delegate:appDelegate delegateQueue:[NSOperationQueue new]];

OMGMultipartFormData *multipartFormData = [OMGMultipartFormData new];
//[multipartFormData addFile:data parameterName:@"file" filename:nil contentType:nil];
[multipartFormData addParameters:[uploadBundle getParameters]];

NSURLRequest *rq = [OMGHTTPURLRQ POST:[uploadBundle.uploadUrl absoluteString] :multipartFormData];

id path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"upload.NSData"];
[rq.HTTPBody writeToFile:path atomically:YES];

[[session uploadTaskWithRequest:rq fromFile:[NSURL fileURLWithPath:path]] resume];

你能分享OMGMultipartFormData文件吗?我已经尝试找到它,但是没有找到。 - Devil
4
这个回答不是很清楚。uploadBundle 是什么?你在使用 id path 这行代码做什么?请简明扼要地解释一下。 - Raptor
OMGMultipartFormData是什么? - Prashant Tukadiya
@MikeAlter @EktaMakadiya 请看一下AFNetworking中的方法multipartFormRequestWithMethod(URLString: parameters: constructingBodyWithBlock: error:)。它使用构造块作为参数,其中包含一个AFMultipartFormData实例,您应该用数据(例如图像或JSON)填充它。以下是Swift中的简单示例:formData.appendPartWithFileData(UIImageJPEGRepresentation(myImage, 1)!, name: "file", fileName: "image.jpg", mimeType: "image/jpg") - sig
就像其他一些人提到的那样,他的答案并没有帮助我们了解OMGMulitpartFormData。您能否更新答案并解释一下OMGMultipartFormData,或者用iOS类中的AFNetworking类替换它? - lostintranslation
显示剩余3条评论

0
问题似乎在于您正在尝试使用“流请求”而不是文件。该代码与
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:[NSURL fileURLWithPath:filePath] progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error){
.... }];
方法一起运行没有任何问题。我还发现,如果您尝试使用文件数据而不是实际文件(使用uploadTaskWithRequest:fromData:progress:completionHandler:),则上传将失败,如{{link1:NSData的上传任务不受后台会话支持}}所述。

所以你一次只能上传一个文件?没有multipartFormData等效物吗? - shim
3
您可以上传多部分数据,但需要将多部分数据保存到文件中,然后再上传该文件。接着,[serializer requestWithMultipartFormRequest:request writingStreamContentsToFile:filePathtemp completionHandler:^(NSError *error) { NSURLSessionUploadTask *uploadTask = [self.activeSessionManager uploadTaskWithRequest:request fromFile:filePathtemp progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {}]; [uploadTask resume]; }]; - tuttu47

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接