Cordova file management I am making an application using Phonegap where users can select and share files. When the user selects it, even if it goes offline or closes the app, I should upload it back to the server, so I need to store the reference file path.

Steps I have used:


User selects/captures video or image using Camera.
File may not contain extension to name in Android every time and in iOS when selected from Gallery.
Get mimeType and then copy the file to myApp's folder with a new name and extension.
Then again get mimeType and return.


Is it correct to copy a file to another location whenever the user selects a media file?

 var obj = {
    destinationType: navigator.camera.DestinationType[fromCamera ? 'FILE_URI' : 'NATIVE_URI'],
    // If I use NATIVE_URI for when taking from Camera it returns null.
    sourceType: navigator.camera.PictureSourceType[fromCamera ? 'CAMERA' : 'PHOTOLIBRARY'],
    mediaType: navigator.camera.MediaType[image ? 'PICTURE' : 'VIDEO']
}, that = this;

if (image &amp;&amp; fromCamera) {
    obj.correctOrientation = true;
    obj.quality = 40;
}

return new Promise(function (resolve, reject) {
    navigator.camera.getPicture(function (url) {
        var fail = function () {
            resolve(false);
        }
        window.setTimeout(function () {
            // mimeType uses window.resolveLocalFileSystemURL to get fileEntry
            that.mimeType(url).then(function (mimeObj) {
                /* 
                    mimeObj contains object like below  
                    {lastModified:'', fileType:'', fileExtension:'', name : ''}
                */
                if (mimeObj) {
                    // that.fileSystem() resolves fileSystem
                    that.fileSystem().then(function (fs) {
                        // dirName is where I want to store all myApp's media files.
                        var dirName = 'myApp/media/' + (image ? "images" : "videos") + '/';
                        that.getFile(url).then(function (fileEntry) {
                            // getFile uses window.resolveLocalFileSystemURL and returns fileEntry
                            that.moveTo(fs, fileEntry, dirName, mimeObj.name).then(function (entry) {
                                // MoveTo fill copy the same file to directory where I am manintaing files.
                                mimeObj.localURL = entry.nativeURL;
                                /* 
                                    mimeObj is failing to find extension 
                                    when user selects it from different albums. But not when user uses Camera. 
                                    So I am making again mimeType call.
                                */
                                that.mimeType(mimeObj.localURL).then(function (mimeObj) {
                                    // This gives me exact mimeObj that I need.
                                    resolve(mimeObj);
                                });
                            }, fail);
                        }, fail);
                    }, fail);
                } else {
                    resolve(false);
                }
            });
        }, 0);

    }, function (fail_message) {
        window.setTimeout(function () {
            reject(fail_message);
        }, 0);
    }, obj);
});
Interesting question,

it is of course not good to fill up memory with copies of pictures. Especially with this scandal in recent memory where deleted pictures haunt users.

It seems from reading your code that you take a copy of the file whether or not you have the extension and MIME type. At least only copy if you see no other way.

Furthermore, from the documentation ( and I could be wrong ), the FileEntry object has a method called file which creates a File Object which has a type property which is the mime type of the file. Could this solve your conundrum ? If that does not work, you should see if you can file a bug.

From a real code review perspective, this is my quick once over:


Respect for dealing with this immature API
JsHint has nothing on this, except for 1 missing semicolon
Have you considered using 'use strict' ?
The multi-line comments definitely stop the reading flow, but removing them would reduce the value of your commenting. I wonder if those multi-liners can be part a narrative on top of your function..
You are at the limit of having to break things up into helper functions, as per this arrow half:

                            });
                        }, fail);
                    }, fail);
                }, fail);
            } else {
                resolve(false);
            }
        });
    }, 0);

}, function (fail_message) {