Ios 我需要上传大量的文件(多达100)到服务器使用AFNetworking在一个单一的流媒体请求,可以提供我上传进度
使用AFNetworking 2.0处理流式请求时,我面临两个挑战 我想上传很多文件(~50MB)到服务器,请求必须是流式的。(否则应用程序将因内存压力而崩溃) 我在AFNetworking 2.0中尝试了各种方法,但都没有成功。 这就是我目前正在做的:Ios 我需要上传大量的文件(多达100)到服务器使用AFNetworking在一个单一的流媒体请求,可以提供我上传进度,ios,afnetworking-2,http-streaming,nsurlsessiontask,Ios,Afnetworking 2,Http Streaming,Nsurlsessiontask,使用AFNetworking 2.0处理流式请求时,我面临两个挑战 我想上传很多文件(~50MB)到服务器,请求必须是流式的。(否则应用程序将因内存压力而崩溃) 我在AFNetworking 2.0中尝试了各种方法,但都没有成功。 这就是我目前正在做的: NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:base
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];
NSMutableURLRequest*request=[[AFHTTPRequestSerializer]multipartFormRequestWithMethod:@“POST”URLString:baseServiceUrl参数:nil constructingBodyWithBlock:^(id formData){
int-imageIndex=0;
for(TempFileUrlList中的NSURL*tempFileUrl){
NSString*文件名=[NSString stringWithFormat:@“图像%d”,图像索引];
n错误*appendError=nil;
[formData appendPartWithFileURL:tempFileUrl名称:文件名错误:&appendError];
imageIndex++;
}
}错误:&错误];
AFHTTPRequestOperation*requestOperation=nil;
requestOperation=[manager HTTPRequestOperationWithRequest:请求成功:^(AFHTTPRequestOperation*操作,id响应对象){
DLog(@“上传文件已完成:%@\n%@”,操作,响应对象);
}失败:^(AFHTTPRequestOperation*操作,NSError*错误){
DLog(@“Error:%@”,Error);
}];
[requestOperation setUploadProgressBlock:^(NSInteger BytesWrite、long long TotalBytesWrite、long long totalBytesExpectedToWrite){
double percentDone=(double)TotalBytesWrite/(double)totalBytesExpectedToWrite;
DLog(@“进度更新(完成百分比):%f”,完成百分比);
}];
[请求操作启动];
这很好,但它不是流式的。如果请求太大,它在内存中准备请求可能会崩溃。我曾尝试过原生套接字和流,但苹果表示,他们可能会因此而不赞成该应用
我尝试过的另一种方法是:
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];
AFHTTPSessionManager*manager=[AFHTTPSessionManager-manager];
NSString*appID=[[NSBundle mainBundle]bundleIdentifier];
NSURLSessionConfiguration*配置=[NSURLSessionConfiguration backgroundSessionConfiguration:appID];
NSURL*serviceUrl=[NSURL URLWithString:baseServiceUrl];
manager=[manager initWithBaseURL:serviceUrl会话配置:配置];
NSURLSessionDataTask*uploadFilesTask=[manager POST:baseServiceUrl参数:nil constructingBodyWithBlock:^(id formData){
int-imageIndex=0;
for(TempFileUrlList中的NSURL*tempFileUrl){
NSString*文件名=[NSString stringWithFormat:@“图像%d”,图像索引];
n错误*appendError=nil;
[formData appendPartWithFileURL:tempFileUrl名称:文件名错误:&appendError];
imageIndex++;
}
}成功:^(NSURLSessionDataTask*任务,id响应对象){
DLog(@“已成功上载的文件:%@\n%@”、任务、响应对象);
}失败:^(NSURLSessionDataTask*任务,NSError*错误){
DLog(@“Error:%@”,Error);
}];
[progressBar设置ProgressWithUploadProgressOfTask:uploadFilesTask动画:true];
但这给了我运行时错误,即:
由于未捕获异常“NSGenericeException”而终止应用程序,
原因:“后台会话中的上载任务必须来自文件”
***第一次抛出调用堆栈:(0 CoreFoundation 0x02cc75e4_uuexceptionpreprocess+180 1 libobjc.A.dylib0x02a4a8b6 objc异常抛出+44 2 CFNetwork
0x0459eb6c-[\uu\NSCFBackgroundSessionBridge uploadTaskForRequest:uploadFile:bodyData:completion:+994 3
CFNetwork 0x045f2f37-[\uu\NSCFURLSession uploadTaskWithStreamedRequest:+73
(必须是流媒体,并且能够在后台继续)我最近自己解决了这个问题 我建议您使用AFNetworking之类的网络库,这样可以避免您执行以前解决过的单调任务 为了在后台真正发送请求,您需要将整个请求写入一个文件,然后使用NSURLSession将其流式传输到服务器(这是可接受的答案--下面的链接),因此,您需要将请求写入磁盘,而无需将整个文件读入内存 您可以流式传输文件(不在后台),如下所示:
NSMutableURLRequest*请求=[[AFHTTPRequestSerializer]multipartFormRequestWithMethod:@“POST”URLString:@”http://example.com/upload“参数:nil constructingBodyWithBlock:^(id
注意:一个简单的解决方案是请求应用程序在后台运行的时间。当对应用程序代理调用ApplicationIdentinterBackground:
时,您可以调用[[UIApplication sharedApplication]beginBackgroundTaskWithExpirationHandler:
请求一些时间在后台运行。([[UIApplication sharedApplication]endBackgroundTask:;
表示您完成了。)您问的缺点是什么?您的时间有限。“如果您不调用endBackgroundTask:对于过期之前的每个任务,系统将终止应用程序。如果您在handler参数中提供了block对象,系统将在过期之前调用您的handler,以便您有机会结束任务。”
:
进步
可以使用子/父关系跟踪多个NSProgress对象的进度。
您可以创建一个NSProgress*overallProgress
对象,然后在创建新请求和[overallProgress resignCurrent]之前调用[overallProgress becomeCurrentWithPendingUnitCount:];
;
之后。您的总体进度对象将反映所有孩子的进度。据我所知,iOS不支持后台上传的流式处理。您需要在后台还是仅在前台支持此功能?如果在前台,您理论上应该能够流式处理?另一个选项是查看服务器端
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileURL:[NSURL fileURLWithPath:@"file://path/to/image.jpg"] name:@"file" fileName:@"filename.jpg" mimeType:@"image/jpeg" error:nil];
} error:nil];
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);
}
enter code here
}];
[uploadTask resume];