NSURLSessionDownloadTask - loading, but ends with an error

I am trying to download a pdf file. earlier, when I used the completion handler block, I was able to see the file at the tmp location. Then I wanted to show the loading process, so I implemented the delegate methods. But now I see how the progress bar and the download file work. but as soon as the download is completed (bytes are written / total bytes = 1), the delegate is called with an error, and there is no file in the tmp directory. What am I missing? below is my code. I downloaded the project at https://www.dropbox.com/s/vn5zwfwx9izq60a/trydownload.zip

@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil]; NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:[NSURL URLWithString:@"http://aayudham.com/URLLoadingSystem.pdf"]]; [downloadTask resume]; } -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { NSLog(@"%@",[error localizedDescription]); } -(void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { dispatch_async(dispatch_get_main_queue(), ^{ _progressBar.progress = (double)totalBytesWritten/(double)totalBytesExpectedToWrite; double value =(double)totalBytesWritten/(double)totalBytesExpectedToWrite; NSLog(@"%f",value); }); } -(void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { } -(void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { NSError *error; //getting docs dir path NSArray * tempArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *docsDir = [tempArray objectAtIndex:0]; //adding folder path NSString *appDir = [docsDir stringByAppendingPathComponent:@"/Reader/"]; NSFileManager *fileManager = [NSFileManager defaultManager]; if(![fileManager fileExistsAtPath:appDir]) { [fileManager createDirectoryAtPath:appDir withIntermediateDirectories:NO attributes:nil error:&error]; } BOOL fileCopied = [fileManager moveItemAtPath:[location path] toPath:[appDir stringByAppendingString:@"/demo.pdf"] error:&error]; NSLog(fileCopied ? @"Yes" : @"No"); } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end 
+8
objective-c nsurlsession
source share
3 answers

@Rob thank you for your quick answers, and it helped me a lot. Here is my code that worked. Hope this helps someone. I can get the actual file name and transfer the file to the directory of my documents using the original name.

 -(void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { NSFileManager *fileManager = [NSFileManager defaultManager]; NSError *error; //getting application document directory path NSArray * tempArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *docsDir = [tempArray objectAtIndex:0]; //adding a new folder to the documents directory path NSString *appDir = [docsDir stringByAppendingPathComponent:@"/Reader/"]; //Checking for directory existence and creating if not already exists if(![fileManager fileExistsAtPath:appDir]) { [fileManager createDirectoryAtPath:appDir withIntermediateDirectories:NO attributes:nil error:&error]; } //retrieving the filename from the response and appending it again to the path //this path "appDir" will be used as the target path appDir = [appDir stringByAppendingFormat:@"/%@",[[downloadTask response] suggestedFilename]]; //checking for file existence and deleting if already present. if([fileManager fileExistsAtPath:appDir]) { NSLog([fileManager removeItemAtPath:appDir error:&error]?@"deleted":@"not deleted"); } //moving the file from temp location to app own directory BOOL fileCopied = [fileManager moveItemAtPath:[location path] toPath:appDir error:&error]; NSLog(fileCopied ? @"Yes" : @"No"); } 
+10
source share

In didFinishDownloadingToURL you should move the file with location to some place more permanent (for example, the Documents folder). If you look for this file in a temporary place later, I won’t be surprised that it no longer exists.

As the documentation says, location is defined as such:

The file URL for the temporary file. Since the file is temporary, you must either open the file for reading or transfer it to a permanent location in the container directory for application sandboxes before returning from this delegate method.

Before returning from didFinishDownloadingToURL you must move the file to a new location.

+6
source share

Just in case, someone had the same problem as me, I thought I posted my solution here.

My problem was that the predicate methods run in the background thread, so I sent a stream "file io", which processes any entries in the files, deletes, etc. in the application.

The problem is that the temporary file is deleted as soon as the delegate method that happened when I switched the threads ends. So when I tried to access the file in my io thread file, it was already deleted.

My solution was to parse the file in NSData in the delegate method and then use NSData to write to the file system in my io thread file.

+3
source share

All Articles