通过NSURLSession上传大视频会导致内存压力崩溃



我使用以下代码将视频上传到服务器,这需要我将视频从视频格式转换为NSData。然而,当视频很大(例如10分钟的视频(时,应用程序会因内存压力而崩溃。我该如何解决此问题?

- (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];
}

p.s.self.video_urlUIImagePickerController给出的文件URL,它只过滤要选择的视频。然后我选择一个10分钟的视频。

附言:我在同一个应用程序中也有AFNetworking,它能帮助后台转移吗?

您应该能够通过使用NSMutableURLRequest并利用其setHTTPBodyStream设置器来实现这一点。

以下是根据我的一些代码改编的片段。它在超过10分钟的视频中处理得很好。大部分是60-90分钟的大视频。

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分钟的视频文件太大,无法存储在内存中

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

确实如此。

解决方案不是将所有请求正文都存储在内存中。最简单的方法是使用NSURLRequest的HTTPBodyStream属性。你可以自己创建NSInputStream,但由于你已经有了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];

最新更新