通过NSURLSession上传大video导致内存压力崩溃

我使用以下代码将video上传到服务器,这需要我将video从video格式转换为NSData 。 但是,当video很大(例如10分钟video)时,由于内存压力,应用程序崩溃。 我该如何解决这个问题?

 - (void)uploadVideo { NSDictionary *params = nil; NSString *NSURLSessionIdentifier = [NSString stringWithFormat:@"%@%@",@"my.bundle.identifier.",[self getTimeString]]; NSURLSessionConfiguration *sessionConfig; // SessionConfiguration With iOS Version if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) { sessionConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:NSURLSessionIdentifier]; } else { sessionConfig = [NSURLSessionConfiguration backgroundSessionConfiguration:NSURLSessionIdentifier]; } sessionConfig.HTTPMaximumConnectionsPerHost = 1; NSURLSession *uploadSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue new]]; OMGMultipartFormData *multipartFormData = [OMGMultipartFormData new]; NSString *url = @"SOME_UPLOAD_URL"; // ========= PROBLEMATIC LINE below ========= self.video_data = [NSData dataWithContentsOfURL:self.video_url]; // ========= PROBLEMATIC LINE above ========= [multipartFormData addFile:self.video_data parameterName:@"file" filename:@"file.mp4" contentType:@"video/mp4"]; NSURLRequest *rq = [OMGHTTPURLRQ POST:url:multipartFormData]; id path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"upload.NSData"]; [rq.HTTPBody writeToFile:path atomically:YES]; [[uploadSession uploadTaskWithRequest:rq fromFile:[NSURL fileURLWithPath:path]] resume]; } 

ps self.video_url是由UIImagePickerController给出的文件URL,它只过滤要select的video。 然后我select一个10分钟的video。

PS我AFNetworking同一个应用程序AFNetworking也可以帮助后台传输?

你应该可以通过使用NSMutableURLRequest并使用它的setHTTPBodyStream setter来实现。

以下是我的一些代码改编的片段。 video处理方式超过10分钟。 大多数是60-90分钟的大video。

 NSData *movieData = [NSData dataWithContentsOfFile:theMovieSourceString]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"video/quicktime" forHTTPHeaderField:@"Content-Type"]; [request setValue:[NSString stringWithFormat:@"attachment; filename=\"%@\"",yourMovieSourceString] forHTTPHeaderField:@"Content-Disposition"]; [request setValue:[NSString stringWithFormat:@"%ld",(unsigned long)[movieData length]] forHTTPHeaderField:@"Content-Length"]; [request setHTTPBodyStream:[NSInputStream inputStreamWithFileAtPath:yourMovieSourceString]]; 

你现在可以在你的NSURLConnection中使用这个请求

 NSURLConnection *connection =[[NSURLConnection alloc] initWithRequest:request delegate:self]; 

问题是显而易见的 – 10分钟的video文件太大,不能存储在内存什么

 self.video_data = [NSData dataWithContentsOfURL:self.video_url]; 

确实。

解决scheme不是将所有请求主体存储在内存中。 最简单的方法是使用NSURLRequest的HTTPBodyStream属性。 你可以自己创buildNSInputStream,但是既然你已经有了AFNetworking,使用它就容易多了。 在我的项目中,我这样做:

 // data.fields is a dictionary with params NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:[url absoluteString] parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { [data.fields enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { [formData appendPartWithFormData:[obj dataUsingEncoding:NSUTF8StringEncoding] name:key]; }]; [formData appendPartWithFileURL:fileURL name:@"file_0" error:&error2]; } error:&error];