Ios 链接后台NSURLSession上载

Ios 链接后台NSURLSession上载,ios,afnetworking-2,nsurlsession,Ios,Afnetworking 2,Nsurlsession,是否有人成功链接NSURLSession后台上传 我试图上传一个巨大的视频文件在5 MB的部分使用背景上传的NSURLSession。上传必须井然有序。整个系统在前景中运行良好。我使用的是AFNetworking,它是一个多部分上传。但当应用程序位于后台时,第一个项目可以正常上传,并在后台启动第二个项目(在AFURLSessionManager的setDidFinishEventsForBackgroundURLSessionBlock中)。但它突然停止(我的最佳猜测是30秒后,因为在后台唤醒的

是否有人成功链接NSURLSession后台上传

我试图上传一个巨大的视频文件在5 MB的部分使用背景上传的NSURLSession。上传必须井然有序。整个系统在前景中运行良好。我使用的是AFNetworking,它是一个多部分上传。但当应用程序位于后台时,第一个项目可以正常上传,并在后台启动第二个项目(在AFURLSessionManager的setDidFinishEventsForBackgroundURLSessionBlock中)。但它突然停止(我的最佳猜测是30秒后,因为在后台唤醒的应用程序的最长生存时间为30秒),然后什么也没发生。我预计第二节课将在后台结束,并调用第三节etc——一种连锁行为,但这似乎不起作用

我尝试过使用HTTPMaximumConnectionsPerHost=1一次性将所有文件部分添加到单个NSURLSession中-这可以很好地工作,并以部分方式上载完整文件。但文件部分是随机挑选的,即第1部分被上传,然后第5部分、第3部分、第10部分等等…。我试着把它添加到一个NSOperationQueue中,操作之间有依赖关系,这似乎把整个事情搞砸了——上传根本不起作用

我知道视频文件可以作为一个单独的文件在后台上传,但服务器希望这在5 MB的部分。因此,我想我唯一的选择是链接上传,或将所有部分添加到NSURLSession,但确保它们始终按照添加顺序上传

任何帮助都将不胜感激

我的代码:

 - (void)viewDidLoad {

    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:[NSString stringWithFormat:@"%d", rand()]];
    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:config];
    config.HTTPMaximumConnectionsPerHost = 1;
    [manager setDidFinishEventsForBackgroundURLSessionBlock:^(NSURLSession *session) {

        dispatch_async(dispatch_get_main_queue(), ^{
            // Call the completion handler to tell the system that there are no other background transfers.
            //                completionHandler();
            [self upload];
        });
    }];
}

- (IBAction)start:(id)sender {

    [self upload];
}

-(void) upload {

    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Sample" ofType:@"mp4"];
    AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];

    NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:@"234", @"u", @"Sample.mp4", @"f",nil];
    NSMutableURLRequest *request = [serializer multipartFormRequestWithMethod:@"POST" URLString:urlString parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        [formData appendPartWithFileURL:[NSURL fileURLWithPath:filePath] name:@"data" fileName:@"Sample.mp4" mimeType:@"video/mp4" error:nil];
    } error:nil];


    __block NSString *tempMultipartFile = [NSTemporaryDirectory() stringByAppendingPathComponent:@"Test"];
    tempMultipartFile = [tempMultipartFile stringByAppendingString:[NSString stringWithFormat:@"%d", rand()]];
    NSURL *filePathtemp = [NSURL fileURLWithPath:tempMultipartFile];
    __block NSProgress *progress = nil;
    [serializer requestWithMultipartFormRequest:request writingStreamContentsToFile:filePathtemp completionHandler:^(NSError *error) {
        NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePathtemp progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {

            NSLog(@"Request--> %@.\n Response --> %@ \n%@",  request.URL.absoluteString ,responseObject, error? [NSString stringWithFormat:@" with error: %@", [error localizedDescription]] : @""); //Lets us know the result including failures
            [[NSFileManager defaultManager] removeItemAtPath:tempMultipartFile error:nil];

        }];
        [uploadTask resume];
        [manager setTaskDidSendBodyDataBlock:^(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {

            NSLog(@"uploading");
        }];
    }];
}
-(void)viewDidLoad{
[超级视图下载];
//加载视图后,通常从nib执行任何其他设置。
NSURLSessionConfiguration*config=[NSURLSessionConfiguration BackgroundSessionConfiguration WithIdentifier:[NSString stringWithFormat:@“%d”,rand()];
AFURLSessionManager*管理器=[[AFURLSessionManager alloc]initWithSessionConfiguration:config];
config.HTTPMaximumConnectionsPerHost=1;
[manager setDidFinishEventsForBackgroundURLSessionBlock:^(NSURLSession*会话){
dispatch\u async(dispatch\u get\u main\u queue()^{
//调用完成处理程序,告诉系统没有其他后台传输。
//completionHandler();
[自我上传];
});
}];
}
-(iAction)开始:(id)发送方{
[自我上传];
}
-(作废)上传{
NSString*文件路径=[[NSBundle mainBundle]pathForResource:@“Sample”类型:@“mp4”];
AFHTTPRequestSerializer*serializer=[AFHTTPRequestSerializer];
NSDictionary*参数=[NSDictionary Dictionary WithObjectsAndKeys:@“234”@“u”@“Sample.mp4”@“f”,nil];
NSMutableURLRequest*request=[serializer multipartFormRequestWithMethod:@“POST”URLString:URLString参数:参数constructingBodyWithBlock:^(id formData){
[formData appendPartWithFileURL:[NSURL fileURLWithPath:filePath]名称:@“数据”文件名:@“Sample.mp4”mimeType:@“video/mp4”错误:nil];
}错误:无];
__block NSString*tempMultipartFile=[NSTemporaryDirectory()stringByAppendingPathComponent:@“测试”];
tempMultipartFile=[tempMultipartFile stringByAppendingString:[NSString stringWithFormat:@“%d”,rand()];
NSURL*filePathtemp=[NSURL fileURLWithPath:tempMultipartFile];
__块NSProgress*进度=零;
[序列化程序requestWithMultipartFormRequest:RequestWritingStreamContentStoFile:filePathtemp completionHandler:^(NSError*错误){
NSURLSessionUploadTask*uploadTask=[manager uploadTaskWithRequest:RequestFromFile:filePathtemp进度:&进度完成处理程序:^(NSURResponse*response,id responseObject,NSError*error){
NSLog(@“Request-->%@.\n Response-->%@\n%@)、Request.URL.absoluteString、responseObject、error?[NSString stringWithFormat:@“with error:%@”,[error localizedDescription]]:@”);//让我们知道结果,包括失败
[[NSFileManager defaultManager]removeItemAtPath:tempMultipartFile错误:nil];
}];
[上传任务恢复];
[manager setTaskDidSendBodyDataBlock:^(NSURLSession*会话,NSURLSessionTask*任务,int64_t bytesSent,int64_t totalBytesSent,int64_t totalBytesExpectedToSend){
NSLog(@“上传”);
}];
}];
}

当你的应用程序运行时,NSOperationQueue就会消失,这在你把它放到后台后不久就会消失。所以这不太管用

取而代之的是,根据您的个人喜好,以磁盘上的文件或NSUserDefaults的顺序存储要上载的剩余文件列表。然后,在后台会话中使用上载任务启动第一个任务。当它完成时,如果你的应用程序没有运行,它应该自动在后台重新启动以处理数据

要支持此行为,请在应用程序:handleEventsForBackgroundURLSession:completionHandler:方法中,像最初一样重新创建后台会话,并存储完成处理程序

此后不久,应该调用请求的委托方法,就像下载完成时应用程序仍在运行一样。除此之外,这些方法还可以为您的应用程序提供来自服务器的响应数据、响应对象(用于检查状态代码)等

当您得到didCompleteWithError委托调用(成功时为nil,IIRC)时,如果传输失败,请重试。如果成功,开始上传下一个文件并更新磁盘上的文件列表

无论哪种方式,在调用会话委托的**urlsessiondFinisheventsforBackgroundUrlSession:*方法时,请调用先前存储的处理程序,大致如下所示:

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    storedHandler();
}];
通过调用完成处理程序,您告诉操作系统您不需要继续运行

冲洗,重复

如果您的应用程序在请求完成时仍在运行,则everyt