Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSURLSessionDownloadTask - read downloaded data before didFinishDownloading

I am trying to replace NSURLConnection with NSURLSession, but I found that with NSURLSession I couldn't read the intermediate data chunks like I did in NSURLConnection with the delegate method.

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

I used to start using the data before completion. I am kind of streaming. How I can access the downloaded data before NSURLSession complete?

I notice there is a (NSURL *)location which is temporary saved data location from NSURLSession before completion, but I can I get this URL before completion?

Thanks


Tried this as suggested from Rob:

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionTask *task = [session dataTaskWithRequest:request];
[task resume];

However, only didRecieveResponse was called

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler

but didReceiveData not called.

I tried to change the task to downloadTask

NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate:self delegateQueue: [NSOperationQueue mainQueue]];
NSURLSessionDownloadTask * downloadTask =[defaultSession downloadTaskWithRequest:request];
[downloadTask resume];

It works with the download delegate, but data delegate (didReceiveData) not called.

Anybody can tell me what did I get wrong?

like image 802
John Avatar asked Aug 23 '14 12:08

John


1 Answers

If you use the delegate-based rendition of NSURLSession, the NSURLSessionDataDelegate protocol includes a didReceiveData method, so you can instantiate a NSURLSessionDataTask and then write your own streaming code just like you would have with NSURLConnection:

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self];
NSURLSessionTask *task = [session dataTaskWithRequest:request];
[task resume];

Alternatively, if you don't want to write your own streaming code, but want NSURLSession to stream this to a file for you and keep you informed of its progress, again, use the delegate based rendition of NSURLSession, create and resume a NSURLSessionDownloadTask:

NSURLSessionTask *task = [session downloadTaskWithRequest:request];
[task resume];

Having done that, you can then implement the didWriteData method of the NSURLSessionDownloadDelegate protocol and it will inform you as data is written (obviously, as long as your app is in the foreground; if you use background session and the app is not active, your app is only re-activated when all the background tasks finish). But that way you get the best of both worlds, where NSURLSession does a streaming download, but will keep you informed of its progress.

But, if you're using NSURLSessionDownloadTask, you don't have access to the NSURL of the temporary file until the download is complete (and in didFinishDownloadingToURL you would move this temporary file to its permanent final location).

like image 62
Rob Avatar answered Oct 25 '22 07:10

Rob