Can't move file after background download: "No such file"

farski picture farski · Nov 27, 2013 · Viewed 7.1k times · Source

I have an app using a backgroundSessionConfiguration instance of NSURLSession to handle some NSURLSessionDownloadTask tasks. The tasks are created correctly, and finish downloading, but in URLSession:downloadTask:didFinishDownloadingToURL: when I go to move the downloaded file from location to a permanent spot on disk, I sometimes (read: often) get the error:

NSUnderlyingError=0x178247890 "The operation couldn’t be completed. No such file or directory"

It's as though the downloaded file is being cleared out of the temp directory (../Library/Caches/com.apple.nsnetworkd/..) before I get a chance to move it.

Running the operation for the same remote file will behave both ways with all other factors being equal, so I haven't been able to identify anything that would cause it to sometimes work.

Is there anyway to ensure that this file will stick around long enough to move it into place once it's done?

Edit: I'm also seeing this with some frequency for normal (not background) sessions as well

Answer

Douglas Ferreira picture Douglas Ferreira · May 16, 2014

The temporary files are deleted automatically after exiting this method, you can try to hold this returned file as an NSData and saves it directly into the desired location.

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {

    // Create a NSFileManager instance
    NSFileManager *fileManager = [[NSFileManager alloc] init];

    // Get the documents directory URL
    NSArray *documentURLs = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
    NSURL *documentsDirectory = [documentURLs firstObject];

    // Get the file name and create a destination URL
    NSString *sendingFileName = [downloadTask.originalRequest.URL lastPathComponent];
    NSURL *destinationUrl = [documentsDirectory URLByAppendingPathComponent:sendingFileName];

    // Hold this file as an NSData and write it to the new location
    NSData *fileData = [NSData dataWithContentsOfURL:location];
    [fileData writeToURL:destinationUrl atomically:NO];
}