Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upload large video via NSURLSession causes memory pressure crash

I use the following codes to upload video to server, which requires me to convert the video from video format to NSData. However, when the video is large (e.g. 10 minute video), the App crashes due to memory pressure. How can I resolve this?

- (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_url is a file URL given by UIImagePickerController which filters only video to choose. I then choose a 10-minute video.

p.s. I got AFNetworking in same App too, can it help with background transfer?

like image 245
Raptor Avatar asked Jul 02 '15 09:07

Raptor


1 Answers

You should be able to this by using a NSMutableURLRequest and utilizing its setHTTPBodyStream setter.

The following are snippets adapted from some code of mine. It handled well for video way over 10 mins. mostly large videos of 60 - 90 minutes.

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

You can now use this request with your NSURLConnection

NSURLConnection *connection =[[NSURLConnection alloc] initWithRequest:request delegate:self];
like image 139
Mike F Avatar answered Oct 11 '22 02:10

Mike F