9
votes

Problem:

In my app, I want to access an image through cordova wkwebview. The HTML element looks as follows.

<img src="cdvfile://localhost/library-nosync/MyFolder/file.jpg">

While loading this, I get error "Failed to load resource: unsupported URL". I am working with iOS 10.2.

Things verified/tried:

If list of files present in "cordova.file.dataDirectory" under folder "MyFolder" is checked, I do see the "file.jpg" present there. It has the native URL as file:///var/mobile/Containers/Data/Application/app_id/Library/NoCloud/MyFolder/file.jpg.

I have added "img-src 'self' cdvfile: " to the Content-Security-Policy.

I have added following in the config.xml

<access origin="cdvfile://*" /> 
<allow-navigation href="cdvfile://*" /> 
<allow-intent href="cdvfile://*" />
<preference name="iosPersistentFileLocation" value="Compatibility" />
<preference name="iosExtraFilesystems" value="library,library-nosync,documents,documents-nosync,cache,bundle,root" />

There are no special (non-ASCII) characters in the URL as mentioned in threads relating to this error. What else could be the reason of "Unsupported URL"?.

Is the way I am accessing cdvfile:// path incorrect?

Update

I came across a link (forgot to capture that) saying the webview needs relative path and hence cdvfile:// would not work. I tried to change the image source to a relative path by changing it to "../../../../../../../../..//var/mobile/Containers/Data/Application/app-id/Library/NoCloud/MyFolder/file.jpg" and I could now see a new error - "Failed to load resource: The operation couldn’t be completed. Operation not permitted"

I could get the image working by "reading" the contents of the file and passing that base64 data as image source. But that is not how it should be, should it?

3
yes, accessing cdvfile:// path is incorrect practice. because browser doesn't understand cdvfile:// protocol. - Arpit Vasani
I have the same issue.... - Daigo Sato
@DarkNeuron - Not really. cdvfile:// does not work with WKWebView - check issues.apache.org/jira/browse/CB-10141 Only two ways known to get this working 1. Create a local http server and use localhost 2. Read the file contents in base64 format and use that as src. I know both are really horrible options, but thats what I know as of today. - Amruta
I ran into this answer: stackoverflow.com/questions/32546965/… Haven't made it work yet, but I'm hopeful. - DarkNeuron

3 Answers

5
votes

If you use the newest ios platform ([email protected]) you can use the scheme and host name options:

<preference name="scheme" value="app" />
<preference name="hostname" value="localhost" />

Then you should get and use the schemeUrl (app://) instead of the cdvfile:// or file:// url.

var cdvfileUrl = "cdvfile://localhost/library-nosync/MyFolder/file.jpg";

// Convert to native url
window.resolveLocalFileSystemURL(cdvfileUrl, function(entry) {
    var nativeUrl = entry.toNativeURL(); // will be "file://...."

    // Use nativeUrl to get scheme friendly url
    var schemeUrl = window.WkWebView.convertFilePath(nativeUrl);  // Will be "app://..."
});

You can use this schemeUrl in your your <img> src tag.

2
votes

For Future reference, with the latest WKWebView, the direct setting of the src attribute fails.

Only way I've found to load the image is something like this:

    function loadImageFromFile(filename, imgElement) {
        // filename is cdvfile:....... (string)
        // imgElement is target IMG element name (string)
        window.resolveLocalFileSystemURL(filename, function success(fileEntry) {
            fileEntry.file(function (file) {
                var reader = new FileReader();
                reader.onloadend = function() {
                    if (reader.result) {
                        var elem = document.getElementById(imgElement);
                        var blob = new Blob([new Uint8Array(reader.result)], { type: "image/png" });
                        elem.src = window.URL.createObjectURL(blob);
                        window.URL.revokeObjectURL(blob);
                    }
                };
                reader.readAsArrayBuffer(file);
            });
        }, function () {
            console.log("File not found: ");
        });
    }
1
votes

If you are using WKWebView, there is only option that you setup a local http web server and then access it via http://localhost ...

Unfortunately "cdvfile" does not works for WKWebView.