Corenet
Corenet

Reputation: 28

Ionic 1 app - trying to serve image files from Cordova dataDirectory

My setup:

local packages: Cordova Platforms : android 6.1.2 ios 4.4.0 Ionic Framework : ionic1 1.3.2 Cordova CLI 7.0.1 and latest ionic as of today

I have an Ionic 1 app that downloads a set of images and stores them via the Cordova file plugin here: cordova.file.dataDirectory. I am then trying to show those images, but having some trouble. I am using a MacBook Pro, Xcode 8, and iOS 10 in a WKWebView (for performance), although I switched to a UIWebView with the same result.

sharedSvc.getDetails($stateParams.id).then(function (data) {
    angular.forEach(imgData, function (value, key) {
        $cordovaFile.checkFile(cordova.file.dataDirectory+data.state+'/'+data.image_id+'/', value.image).then(function (success) {
            $scope.imgArr.push({src: cordova.file.dataDirectory+data.state+'/'+data.image_id+'/'+value.image});
            console.log('PUSHING - '+imgSrc);
        }, function(error) {
            console.log('Check for file bad1: '+cordova.file.dataDirectory+data.state+'/'+data.image_id+'/'+value.image);
            //console.log(JSON.stringify(error));
        });
    });
});

Then I am trying to show the images:

<img ng-repeat="image in imgArr" src="{{image.src}}" />

For reference, I have the following items in my config.xml file:

<access allows-arbitrary-loads-in-media="true" allows-arbitrary-loads-in-web-content="true" allows-local-networking="true" origin="*" />
<access allows-arbitrary-loads-in-media="true" allows-arbitrary-loads-in-web-content="true" allows-local-networking="true" origin="file:///*" />
<allow-navigation href="file://*/*" />
<allow-intent href="file://*/*" />

Some of those may be unnecessary, but they have been added while I was looking for possible answers. Some pointed me towards issues with whitelisting, hence the additions.

I can verify the images are there, as shown in the checkFile call in the top code block. When I navigate to those images manually, they are there and the correct size. Also, the console logs are showing proper path to the files. However, when the app runs in the simulator (and on my physical device), the images are blank.

After searching all day for a solution, I am asking for some assistance from the code pros here. Thanks!

Upvotes: 0

Views: 615

Answers (1)

DaveAlden
DaveAlden

Reputation: 30356

WKWebView blocks access to files outside of the directory in which the source page is located, i.e. www where index.html resides. When you download data to cordova.file.dataDirectory, the filepath is on a different subtree so WKWebView is unable to access the files.

One solution, as outlined here, is to load the images using cordova-plugin-file as blobs which can be turned into a URL which WKWebView will accept:

function fetchLocalFileViaCordovaAsArrayBuffer(filename, successCallback, errorCallback)
{
    fetchLocalFileViaCordova(filename, function (file)
    {
        var reader = new FileReader();

        reader.onload = function (e)
        {
            successCallback(e.target.result);
        };

        reader.readAsArrayBuffer(file);
    }, errorCallback);
};

function fetchLocalFileViaCordovaAsURL(filename, successCallback, errorCallback)
{
    // Convert fake Cordova file to a real Blob object, which we can create a URL to.
    fetchLocalFileViaCordovaAsArrayBuffer(filename, function (arrayBuffer)
    {
        var blob = new Blob([arrayBuffer]);
        var url = URL.createObjectURL(blob);
        successCallback(url);
    }, errorCallback);
};

sharedSvc.getDetails($stateParams.id).then(function (data) {
    angular.forEach(imgData, function (value, key) {
        $cordovaFile.checkFile(cordova.file.dataDirectory+data.state+'/'+data.image_id+'/', value.image).then(function (success) {
            fetchLocalFileViaCordovaAsURL(cordova.file.dataDirectory+data.state+'/'+data.image_id+'/'+value.image, function(url){
                $scope.imgArr.push({src: url});
                console.log('PUSHING - '+imgSrc);
            });
        }, function(error) {
            console.log('Check for file bad1: '+cordova.file.dataDirectory+data.state+'/'+data.image_id+'/'+value.image);
            //console.log(JSON.stringify(error));
        });
    });
});

Upvotes: 2

Related Questions