Question

Using Cordova/PhoneGap 3.3.0, I am downloading a file using the FileTransfer plugin, and then trying to open it using the InAppBrowser plugin. I can download the file successfully, and place it in the temp directory. Since the File plugin now uses URL schema, I cannot figure out how to pass the correct url/path to the window.open method of the InAppBrowser plugin. I cannot find any relevant documentation either. All of the "download and open" documentation I can find is out of date and pre-URL-schema.

Relevant links:

Out of date examples I found:

Here is my code:

var uri = encodeURI("http://some.url/file.pdf");
window.requestFileSystem(LocalFileSystem.TEMPORARY, 0,
    function (fileSystem) {
        var fileTransfer = new FileTransfer();
        var filename = fileSystem.root.toURL() + uri.substr(uri.lastIndexOf("/") + 1);
        fileTransfer.download(uri, filename,
            function(entry) { // download success
                var path = entry.toURL(); //**THIS IS WHAT I NEED**
                window.open(path, "_system");
            },
            function(error) {} // irrelevant download error
        );
    },
    function(error) {} // irrelevant request fileSystem error
);

I am currently testing in Android on a Nexus 7 and Nexus 5. The InAppBrowser correctly opens the default pdf launcher (in my case Adobe Reader), but then I get a "The document path is not valid" error.

[Update: showing return values]

I have tried all of the following combinations for the file path:

var path = entry.toURL(); // "cdvfile://localhost/temporary/file.pdf"
var path = entry.fullPath; // "file.pdf"
var path = fileSystem.root.toURL() + filename; // "cdvfile://localhost/temporary/file.pdf"
var path = fileSystem.root.fullPath + filename; // "/file.pdf"
Was it helpful?

Solution 2

I THINK I have a solution to this, but it's kinda nasty.

I grepped through the cordova JAVA and looked for places it constructed a file entry JSON object. Specifically by looking for places where its adding fullPath to the object.

I added an additional entry for "fullAbsolutePath" with the value [file].getAbsolutePath(), where [file] is whatever java.io.file instance is nearby. I did this in all the places I could find just to be safe and because it doesn't seem to hurt anything.

Then I modified FileEntry.js and File.js in the plugins\file folder to also populate that value to the file entry object.

Still trying to work out the kinks, but I believe I'm on the right track...

I think a better solution would be to modify the inAppBrowser plugin to recognize and resolve the cordovaFile:// protocol and im sure they obscured the absolute file system path on purpose - but that might be a bit beyond me.

EDIT - Yup! this works! I can now take a file entry, call the file method, then read fullSystemPath off the fileObject. Value is like "/storage/emulated/0/whatever/" on my android. Just need to prepend "file://" and window.open will accept it.

OTHER TIPS

Since Cordova 3.4 the file protocol has changed and instead of using fullPath they now provide the toURL() that returns a cdvfile://path/to/your/file.ext path.

So when you download a file using the filesystem object's callback (with the entry argument) just call the entry.toURL() and open this using the following statement to open it - assuming you have InApBrowser installed and the _blank will open the InAppBrowser's window:

window.open(entry.toURL(), '_blank', 'location=no,closebuttoncaption=Close,enableViewportScale=yes');  

I wrote about it in this post on my blog (if you want all the references and background info).

In the latest cordova docs they say

If you are upgrading to a new (1.0.0 or newer) version of File, and you have previously been using entry.fullPath as arguments to download() or upload(), then you will need to change your code to use filesystem URLs instead.

FileEntry.toURL() and DirectoryEntry.toURL() return a filesystem URL of the form

cdvfile://localhost/persistent/path/to/file which can be used in place of the absolute file path in both download() and upload() methods.

What you can try is remove cdvfile://localhost/persistent to have a url that would work with your window.open. (maybe start with a alert or console.log of what you get with entry.toURL())

In current plugin dev branch there is a solution:

Entry.toNativeURL() - Returns the full path to the file in the device FileSystem.

https://github.com/apache/cordova-plugin-file/tree/dev

I know this is answered already, but I had the most success with entry.toInternalURL().

The path that follow to "cdvfile://localhost/persistent" is like a root app (www folder) path. In other words, I mean you have access to the images or downloaded files using the path that follow "cdvfile://localhost/persistent".

Example

Download target Path: "cdvfile://localhost/persistent/MyImages/thebestimageever.jpg"

In a HTML image tag I could do this: <img src="/MyImages/thebestimageever.jpg" />

And it works well.

Just write the window.open within the download method or ask for file system and entry again before opening if you want to make it separately

function downloadFile(fileURL, destination, fileName) {
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fileSystem) {
    fileSystem.root.getDirectory(destination, {
        create: true
    }, function (dirEntry) {
        var ft = new FileTransfer();
        ft.download(fileURL, dirEntry.toURL() + "/fileName", function (entry) {
            alert(fileName + " downloaded successfully at:" + dirEntry.fullPath);
            window.open(dirEntry.toURL() + "fileName", "_blank", "location=yes");
        }, function (error) {
            alert("download failed: " + JSON.stringify(error));
        });
    }, function (error) {
        alert("dir creation failed: " + JSON.stringify(error));
    });
}, function (error) {
    alert("requesting file system failed: " + JSON.stringify(error));
});

}

if your destination is more than one folder level then you have to ask for getDirectory recursively one by one (if your folders are already created then one call of the method is enough)

PS: - on iOS files are downloaded to 'Documents' folder and not to 'www' so not the same location of your app.js content as some people say - if you are opening a html page with js and css from a downloaded unzipped folder then you have to make some changes on InAppBrowser.m to make it load properly

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top