Transferring a file gives "Could not create target file"

1,885 views
Skip to first unread message

Raymond Camden

unread,
Jun 28, 2014, 5:16:19 PM6/28/14
to phon...@googlegroups.com
Testing on iOS, simulator and device.

I've got a DirectoryEntry object created from cordova.file.applicationStorageDirectory:

window.resolveLocalFileSystemURL(cordova.file.applicationStorageDirectory, function(ob) {

This works just fine. I then check to see if a file exists in this directory, and if not, I do a FileTransfer:

function downloadAsset() {
var fileTransfer = new FileTransfer();
console.log("About to start transfer");
fileTransfer.download(assetURL, storeOb.fullPath + fileName, 
function(entry) {
console.log("Success!");
appStart();
}, 
function(err) {
console.log("Error");
console.dir(err);
});
}

On iOS Simulator, this works perfectly. On my device, I get:

[Log] Object (app.js, line 56)
body: "Could not create target file"
code: 1
http_status: 200
target: "file:////var/mobile/Applications/86518529-638B-4676-9A0B-E5966D1751FD/data.txt"
__proto__: Object

I tried storeOb.toURL() as well, but it didn't work. Any ideas?

Raymond Camden

unread,
Jun 28, 2014, 5:19:51 PM6/28/14
to phon...@googlegroups.com
According to the docs for FileTransfer, it seems to imply I *must* use toURL(), so I've switched my code to that, but it still doesn't work.

I output the path and it is this: file:////var/mobile/Applications/86518529-638B-4676-9A0B-E5966D1751FD/data.txt 

It doesn't have cdvfile as the scheme as the docs describe though.

Raymond Camden

unread,
Jun 28, 2014, 5:23:20 PM6/28/14
to phon...@googlegroups.com
*sigh*

So, the FileSystem docs mention that if you use toInternalURL(), you get the new cdv style URLs. This does not match the FileTransfer docs.

But I tried it.

And it gave the same error.

Kerri Shotts

unread,
Jun 28, 2014, 9:11:02 PM6/28/14
to phon...@googlegroups.com
So what are you using for cdvfile://?

Something like cdvfile://localhost/persistent/data.txt"

Kerri Shotts

unread,
Jun 28, 2014, 9:14:02 PM6/28/14
to phon...@googlegroups.com
Also -- try targeting the documents directory rather than the root of the application container. If you have file 1.2.0, you should be able to use cordova.file.dataDirectory + the filename.

Raymond Camden

unread,
Jun 28, 2014, 9:53:13 PM6/28/14
to phon...@googlegroups.com
As I mentioned, cordova.file.applicationStorageDirectory, which I convert into a directoryEntry.

I then create a path like so:

storeOb.toInternalURL() + fileName

I tried .fullPath, toURL, and toInternalURL. All failed.



--
-- You received this message because you are subscribed to the Google
Groups "phonegap" group.
To post to this group, send email to phon...@googlegroups.com
To unsubscribe from this group, send email to
phonegap+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/phonegap?hl=en?hl=en
 
For more info on PhoneGap or to download the code go to www.phonegap.com
---
You received this message because you are subscribed to a topic in the Google Groups "phonegap" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/phonegap/W1ZR6WG5XwM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to phonegap+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
===========================================================================
Raymond Camden, Web Developer for Adobe

Email : raymon...@gmail.com
Blog : www.raymondcamden.com
Twitter: raymondcamden

Raymond Camden

unread,
Jun 28, 2014, 9:53:40 PM6/28/14
to phon...@googlegroups.com
I'm targeting cordova.file.applicationStorageDirectory.


--
-- You received this message because you are subscribed to the Google
Groups "phonegap" group.
To post to this group, send email to phon...@googlegroups.com
To unsubscribe from this group, send email to
phonegap+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/phonegap?hl=en?hl=en
 
For more info on PhoneGap or to download the code go to www.phonegap.com
---
You received this message because you are subscribed to a topic in the Google Groups "phonegap" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/phonegap/W1ZR6WG5XwM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to phonegap+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Kerri Shotts

unread,
Jun 28, 2014, 11:18:28 PM6/28/14
to phon...@googlegroups.com
So you did mention that; my bad.

The error message does not clearly indicate to the failure point in the plugin -- it could be that the plugin can't resolve the path, or it could be that the plugin doesn't have permissions to create a file at the given location, based on what I see in the source code.

A couple ideas:
  • Your Url scheme is "file:////path/to/file", at least from the OP. Not sure if that's a typo or if that's what you're actually getting -- but note the four slashes. I would expect "file:///path/to/file" (three slashes)
  • Try using some of the other cordova.file.* properties or go down into a known directory (like /Documents): it looks like you're creating a file in the root directory of the application container, which is unusual, at least to my eyes. It really should be going to /Documents, /Library/Caches or /tmp (depending on the type of data).
Also note that the iOS simulator isn't sandboxed like the app is, and so just because a file operation succeeds on the simulator does not guarantee that it will work on the device.  

Hope that helps?

Raymond Camden

unread,
Jun 28, 2014, 11:55:23 PM6/28/14
to phon...@googlegroups.com
Hmm - but why would cordova.file.applicationStorageDirectory be unusual? According to the docs, this is "Root of app's private writable storage" - which should be... well writable. ;)

As for the quadruple slash - that came right from Safari's remote debug panel.


On Sat, Jun 28, 2014 at 10:18 PM, Kerri Shotts <kerri...@gmail.com> wrote:
So you did mention that; my bad.

The error message does not clearly indicate to the failure point in the plugin -- it could be that the plugin can't resolve the path, or it could be that the plugin doesn't have permissions to create a file at the given location, based on what I see in the source code.

A couple ideas:
  • Your Url scheme is "file:////path/to/file", at least from the OP. Not sure if that's a typo or if that's what you're actually getting -- but note the four slashes. I would expect "file:///path/to/file" (three slashes)
  • Try using some of the other cordova.file.* properties or go down into a known directory (like /Documents): it looks like you're creating a file in the root directory of the application container, which is unusual, at least to my eyes. It really should be going to /Documents, /Library/Caches or /tmp (depending on the type of data).
Also note that the iOS simulator isn't sandboxed like the app is, and so just because a file operation succeeds on the simulator does not guarantee that it will work on the device.  

Hope that helps?


Raymond Camden

unread,
Jun 29, 2014, 12:03:04 PM6/29/14
to phon...@googlegroups.com
If folks want to see the entire app, you can see it here:


It is *incredibly* simple. Check for a file, and if not there, fetch it. 

Raymond Camden

unread,
Jun 29, 2014, 12:55:06 PM6/29/14
to phon...@googlegroups.com
Update:

Switching to cordova.file.dataDirectory worked perfectly.

So I see two issues here:

a) When I read the description of cordova.file.applicationStorageDirectory, it says: " Root of app's private writable storage." To me, that translates as: "I can write here, and store crap here, and it is private, ie not readable by other apps." When you compare that to dataDirectory, "Where to put app-specific data files.", it feels like dataDirectory is a similar type location, ie, I can put crap there, but it is NOT private. That could be desirable. I may want files downloadable by app X to be readable by other apps. 

Point is - obviously I'm misreading applicationStorageDirectory. Maybe I'm not. But we need clarification there. I'm going to raise this on the Cordova dev list as I think it is a documentation issue. 

b) The docs for FileTransfer state suggest using toURL. Ok, I had more to write me but I just confirmed it DOES work. I didn't need to use toInternalURL.

So I guess A is the main issue here.


On Saturday, June 28, 2014 4:16:19 PM UTC-5, Raymond Camden wrote:

jcesarmobile

unread,
Jun 30, 2014, 2:16:16 AM6/30/14
to phon...@googlegroups.com
I just did some tests on iOS

cordova.file.applicationStorageDirectory is in fact the root app folder as you say, it's writable on the simulator, but it isn't writable on a real device, you have to write in one of the mentioned by Kerri, Documents, Library, Caches or tmp.

On iOS all your app data is private, it doesn't matter the folder where you store it as you can only store the data inside the app folder and the apps are sandboxed. The app data can't be read by other apps (not on iOS 7, I haven't read yet how it works on iOS 8). You can open the a file from your app in another app, but you have to manually select the file and choose wich other app will open it (see andrew trice "open with" plugin)

So I suppose the documentation might be right for android but it's wrong for iOS (not really sure it's right for android as I don't think you can really have private data on android)

Kerri Shotts

unread,
Jun 30, 2014, 2:30:55 PM6/30/14
to phon...@googlegroups.com
So, I agree the wording on this is fuzzy at best and certainly misleading. Having done native development, I'm already accustomed to the quirks of the iOS file system, and so back-read this knowledge into the docs. Even so, the docs should certainly be updated to include a note that cordova.file.applicationStorageDirectory is read-only (at least for iOS). It might be better worded as "the root directory of the application's sandbox; on iOS this location is read-only (but specific subdirectories [Documents, Caches, tmp] are read-write). All data contained within is private to the app." dataDirectory could be worded "persistent and private data storage within the application's sandbox using internal memory (on Android, if you need to use external memory, use externalDataDirectory). On iOS, this directory is not synced with iCloud (use syncedDataDirectory)." Or some such. 

As for private data on android: the data in internal storage (not on the sdcard) should be sandboxed (unless rooted and superuser), right? Although which persistent store for the file API is used depends on a setting in config.xml, I /would/ expect that dataDirectory would be /data/data (and private) whereas externalDataDirectory would be on the sdcard (and public). I should play with this more.

It would be nice if the docs would describe the hierarchy a bit, like this (for iOS, IIRC):

  Directory Path                     cordova.file property      read-write     persistent?    OS may clear?    sync?     private?
  /var/mobile/Applications/uuid/     applicationStorageDirectory  (r/o)            N/A              N/A         N/A        Yes
    appname.app/                     applicationDirectory         (r/o)            N/A              N/A         N/A        Yes
      www/                           -                            (r/o)
    Documents/                       documentsDirectory           (r/w)            Yes              No          Yes        Yes
    Library/                         -                            (r/w)
      NoCloud/                       dataDirectory                (r/w)            Yes              No          No         Yes 
      Cloud/                         syncedDataDirectory          (r/w)            Yes              No          Yes        Yes
      Caches/                        cacheDirectory               (r/w)            Yes*             Yes***      No         Yes
    tmp/                             tempDirectory                (r/w)            No**             Yes***      No         Yes

   * Files persist across app restarts and upgrades, but this directory can be cleared whenever the OS desires. Your app should
     be able to recreate any content that might be deleted.
  ** Files may persist across app restarts, but do not rely on this behavior. Files are not guaranteed to persist across updates.
     Your app should remove files from this directory when it is applicable, as the OS does not guarantee when (or even if) these
     files are removed.
 *** The OS may clear the contents of this directory whenever it feels it is necessary, but do not rely on this. You should clear
     this directory as appropriate for your application.

Raymond Camden

unread,
Jun 30, 2014, 2:39:32 PM6/30/14
to phon...@googlegroups.com
Kerri, do you want to do a PR with edits for this? If not - I will and totally take credit for your write up. (Ok, maybe not.)


--
-- You received this message because you are subscribed to the Google
Groups "phonegap" group.
To post to this group, send email to phon...@googlegroups.com
To unsubscribe from this group, send email to
phonegap+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/phonegap?hl=en?hl=en
 
For more info on PhoneGap or to download the code go to www.phonegap.com
---
You received this message because you are subscribed to a topic in the Google Groups "phonegap" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/phonegap/W1ZR6WG5XwM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to phonegap+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Kerri Shotts

unread,
Jun 30, 2014, 3:24:30 PM6/30/14
to phon...@googlegroups.com
Sure; I can submit a PR for it. :-) 

Raymond Camden

unread,
Jun 30, 2014, 3:29:45 PM6/30/14
to phon...@googlegroups.com
Thanks - I appreciate it. 

Kerri Shotts

unread,
Jun 30, 2014, 9:20:58 PM6/30/14
to phon...@googlegroups.com
Pull request #59; Bug # CB-7057.

Raymond Camden

unread,
Jul 1, 2014, 11:19:47 AM7/1/14
to phon...@googlegroups.com
Thank you Kerri. This is directly going into my samples project to help others, so it is appreciated. :)
Reply all
Reply to author
Forward
0 new messages