Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 我需要上传大量的文件(多达100)到服务器使用AFNetworking在一个单一的流媒体请求,可以提供我上传进度_Ios_Afnetworking 2_Http Streaming_Nsurlsessiontask - Fatal编程技术网

Ios 我需要上传大量的文件(多达100)到服务器使用AFNetworking在一个单一的流媒体请求,可以提供我上传进度

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

使用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];
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.dylib
0x02a4a8b6 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];