2

I am implementing a resumable upload protocol that uploads in the background on iOS, which means I have to use an NSURLSessionUploadTask with a file. Since it's a resumable upload protocol, the file needs to be truncated based on the data that has already been received by the server, so I need to save a new temporary file to disk that has only the bytes to be uploaded within it.

If I can create that temporary upload file in the tmp/ or /Library/Caches/, can I trust that it will be kept as long as the NSURLSession is running?

EDIT: When an upload fails, the server will be saving the bytes it has already received and communicating that to the client. The client then should only send part of the file, which is why I need to create a smaller temporary file that must not be deleted mid-upload.

JustinHK
  • 758
  • 1
  • 6
  • 19

2 Answers2

0

The answer to your question is no. NSURLSessionUploadTask's description appears to support keeping the source file around but it's misleading:

"In iOS, when you create an upload task for a file in a background session, the system copies that file to a temporary location and streams data from there"

But it says nothing about whether it will keep the original source file in the tmp directory. Specifically for your case where your server supports uploading partial files and you need to restart them after failures. Or in the more common situation where you need to manually restart an entire failed upload, for example from a retry-able server error, or if user killed your app and then restarted it (iOS doesn't continue uploads for user killed apps).

In these cases you can't count on the file still being around if you create it in the apps tmp directory. The file system programming guide tells us this.

https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html

"Use this directory to write temporary files that do not need to persist between launches of your app. Your app should remove files from this directory when they are no longer needed; however, the system may purge this directory when your app is not running. The contents of this directory are not backed up by iTunes or iCloud."

So any tmp directory files can be deleted by iOS when your app stops running, and I can confirm I've seen this in production releases of our app. If you think you may need the source file for the upload again, you must store it in your own app directory, and manage deleting it yourself when done with it. Sorry, extra work, but I don't know of any way around it.

SafeFastExpressive
  • 3,637
  • 2
  • 32
  • 39
-1

Huh? You provide the entire file, and the system takes care of managing the partial upload/download, and notifies you once the transfer is complete. In the case of a download, t hands you a temporary file once the download is complete and you have to save it to a permanent location.

You should not be mucking around with partial files at all.

EDIT:

You don't have access to tmp or /Library/Caches/, except through the sandbox. You can get access to the caches directory with the call

[NSSearchPathForDirectoriesInDomains(
  NSCachesDirectory, 
  NSUserDomainMask, YES) lastObject];

It's my understanding that the caches directory only gets purged on restart, or if the device gets critically low on space, but I seem to remember that the docs are vague on when, exactly, the caches directory gets cleared.

You would probably be better off saving your file to the documents directory, then deleting it once you're done with it.

Community
  • 1
  • 1
Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • I think the "partial file" thing is just an aspect of what the server is expecting, not a NSURLSession-specific comment. I would interpret the question to mean "Where can I save the files that I provide to an NSURLSessionUploadTask in a background session so that they don't get deleted before the task completes, and how do I set the file protection correctly?". – dgatwood May 18 '16 at 21:12
  • @dgatwood - That's what I meant, correct. The server will expect only part of a file, since we may have uploaded some of it already. – JustinHK May 18 '16 at 23:03
  • "The server will expect only part of a file, since we may have uploaded some of it already." That is wrong. The URL session manages this for you. You don't have to keep track of the part you've already uploaded and continue the upload "mid-stream". The background upload/download feature of NSURLSession takes care of that. – Duncan C May 18 '16 at 23:27
  • 1
    @DuncanC HTTP does not support that by default. If you start an upload in HTTP and it fails, the NSURLSession must start over from the beginning, which is not what I want because I am uploading large files over cellular networks. In particular, we are using the TUS protocol: https://github.com/tus/tus-resumable-upload-protocol/blob/master/protocol.md – JustinHK May 19 '16 at 18:42
  • Ok, now we're getting somewhere. Perhaps you should document the specifics of your custom server code and how it differs from standard handling of HTTP uploads. – Duncan C May 19 '16 at 18:43
  • @DuncanC I added a reference to my previous comment. – JustinHK May 19 '16 at 18:45
  • 1
    To be honest the intent is kind of irrelevant to the question, which is if I save a file to /tmp, will the NSURLSession keep it there when my app is killed? – JustinHK May 19 '16 at 18:47
  • The reason I was probing intent is that your question did not seem to make sense. This sounded like an [**XY problem**](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) to me to me. – Duncan C May 20 '16 at 14:31