Nico Westerdale
Nico Westerdale

Reputation: 2186

"Not allowed to load local resource" for Local image from Remote page in PhoneGap Build

I'm hosting my webpages for a phonegap build app. I'd like to use the camera to upload a photo, and show a preview the image, basically doing this:

<img src="file:///storage/emulated/0/Android/data/com.myapp.myapp/cache/1470418568917.jpg" height="500" />

Because my pages are hosted I'm getting this error:

Not allowed to load local resource: file:///storage/emulated/0/Android/data/com.myapp.myapp/cache/1470418568917.jpg", source: https://www.myapp.com/v5.5/imager.html#

I assume that this is some CORS problem, so I've added this to the html of the page

<meta http-equiv="Content-Security-Policy" content="default-src *; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'; media-src *; img-src * filesystem: data:">

and this to my config.xml (I'm using Phonegap Build)

 <plugin name="cordova-plugin-whitelist" source="npm" />

 <allow-navigation href="*" />
 <allow-navigation href="*://*/*" />
 <allow-navigation href="file:///*/*" />
 <allow-navigation href="http://*/*" />
 <allow-navigation href="https://*/*" />
 <allow-navigation href="data:*" />

 <allow-intent href="*" />
 <allow-intent href="http://*/*" />
 <allow-intent href="https://*/*" />
 <allow-intent href="tel:*" />
 <allow-intent href="sms:*" />
 <allow-intent href="mailto:*" />
 <allow-intent href="geo:*" />

 <access origin="*" />
 <access origin="*://*/*" />
 <access origin="file:///*" />
 <access origin="cdvfile://*" />
 <access origin="content:///*" />

As you can see I've tried every setting I can think of, from scouring the web. Am I missing something obvious?

Thanks in advance.

Upvotes: 23

Views: 32921

Answers (10)

atull
atull

Reputation: 1

Android

With the release of cordova-plugin-file 7.0.0 we can now use Entry.toURL() to get the localhost path to the file as below

window.resolveLocalFileSystemURL(path, function (fileEntry) {
    image.src = fileEntry.toURL();
});

This removes the need for the AndroidInsecureFileModeEnabled preference

IOS

To add to Thomas' answer for iOS, if you're using AngularJS and you get an error like

Refused to load unsafe:app://...

you need to add your scheme (app) to AngularJS's whitelist for images to load. This can be done using

$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|blob|app):|data:image//);

Upvotes: 0

Thomas
Thomas

Reputation: 311

Android

Looks like Google listed the file location as insecure. From cordova 10 up it is flagged as so. You can still use it with this preference in the config.xml

<preference name="AndroidInsecureFileModeEnabled" value="true" />

Here is more information: https://cordova.apache.org/announcements/2021/07/20/cordova-android-10.0.0.html

iOS

On iOS working with scheme paths solved the problem for me:

window.WkWebView.convertFilePath(cordova.file.dataDirectory + path)

You have to add this preference in your config.xml make this work:

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

Upvotes: 3

Hrushikesh Sawant
Hrushikesh Sawant

Reputation: 74

Ionic 4-5 users please take note. Webview is not allowed to read from storage. By using the method image is loaded as local host resource. Fetching from device just url is manipulated.

in .html

<img [src]="getTrustImg(imageSrc)" />

in .ts

private win: any = window;

getTrustImg(imageSrc){
let path = this.win.Ionic.WebView.convertFileSrc(imageSrc);
console.log(path);
return path;
}

Upvotes: 1

Mykyta Chernenky
Mykyta Chernenky

Reputation: 31

This is the only thing that worked for me: window['Ionic']['WebView'].convertFileSrc(yourURL);

Upvotes: 2

Russ
Russ

Reputation: 631

The answer from @Vladyslav Goloshchapov is the correct one for my situation (using the non-deprecated form).

I'm trying to open an Ionic app from within an Ionic app (both Ionic 4) using phonegap-plugin-contentsync which allows you to download and unzip a file (an Ionic app in my case) into the local filesystem. (The 2nd app isn't a published app).

I used this as: window.location.href = window.Ionic.WebView.convertFileSrc(url); for iOS.

Android is not as complicated so you can use window.open(url, '_self');

My URL is in the format (for iOS): file:///var/mobile/Containers/Data/Application/[UUID]/Library/NoCloud/[appFolder]/index.html

Upvotes: 2

Alok Singh
Alok Singh

Reputation: 27

This is working with ionic 3 and you can use below to resolve the issue for Not allowed to load local resourse

First put these things in home.ts

import { Base64 } from '@ionic-native/base64';
import { DomSanitizer, SafeResourceUrl, SafeUrl } from 
'@angular/platform-browser';

//inside the export class
base64Image:any;
croppedImage = null;

constructor(
  public base64:Base64,
  public domSanitizer:DomSanitizer,
) {}    

selectImage() {
const options: CameraOptions = {
  quality: 100,
  destinationType: this.camera.DestinationType.FILE_URI,
  encodingType: this.camera.EncodingType.JPEG,
  mediaType: this.camera.MediaType.PICTURE,
  correctOrientation: true,
  sourceType:0,
}
  this.croppedImage = null;
  this.camera.getPicture(options).then((imageData) => {
  this.croppedImage = imageData;
  this.crop.crop(this.croppedImage, {quality: 100,targetWidth: -1, targetHeight: 
-1 })
.then(
newImage => {
  this.base64.encodeFile(newImage).then((base64File: string) => {
  let imageSrc = base64File.split(",");
  this.base64Image = 'data:image/jpeg;base64,' + imageSrc[1];
  this.croppedImage = 
  this.domSanitizer.bypassSecurityTrustUrl('data:image/jpeg;base64,' + 
imageSrc[1]);
}, (err) => {
  console.log(err);
});
  console.log('new image path is: ' + newImage);
},
error => {
  console.error('Error cropping image', error);
}
);
//  this.myImage = 'data:image/jpeg;base64,' + imageData;
});
}   

Then now in the view home.html put below things

    <button ion-button full (click)="selectImage()" 
 *ngIf="!base64Image">Gallery</button>
    <button ion-button full (click)="selectImageFromCamera()">Camera</button>
    <ion-row *ngIf="croppedImage">
       <ion-card>
          <ion-card-header>Cropped Image</ion-card-header>
          <ion-card-content padding>
             <img [src]="croppedImage">
          </ion-card-content>
       </ion-card>
    </ion-row>`enter code here`

Upvotes: 1

ImFarhad
ImFarhad

Reputation: 3209

I was working on ionic3 app and testing the console using chrome inspector. I was also running and emulating with the --livereload Flag, It was not showing image not on emulator nor on real device. I go to Above mentioned link and imported the module
import { normalizeURL } from 'ionic-angular';
on the success callback of my image capture function, I passed the path like this and it worked like a charm.
After investigating a little bit more, I found out that its because of --livereload Flag, I removed the flag from command , run the programme with the following command and its showing image now:
ionic cordova run android

    takePhoto() {
        this.camera.getPicture(this.getCameraOptions()).then((imageData) => {
         this.isPhotoTaken = true;
         this.photo = normalizeURL(imageData); 
         console.log("PHOTO PATH: "+ this.photo)
        }, (err) => {
            console.error('IMAGE CAPTURE ERROR: ' + err);
        });
      }

     setCameraOptions() {    
        const options = {
          quality: 100,
          sourceType: this.camera.PictureSourceType.CAMERA,
          saveToPhotoAlbum: false,
          correctOrientation: true
        };
        return options;
      }

  getCameraOptions(): CameraOptions{
    return this.setCameraOptions();
  }

Upvotes: 0

Vladyslav Goloshchapov
Vladyslav Goloshchapov

Reputation: 136

I have recently faced same issue. Appears that cordova ios app is run on localhost:8080 internally, this is main reason why it doesn`t allow to load files from "file://" protocol.

easy fix - "var workingPath = window.Ionic.normalizeURL(givenPath)";

Please read article from IONIC about that - https://ionicframework.com/docs/wkwebview/

Upvotes: 11

niczak
niczak

Reputation: 3917

Something to note here for future users who run into this, be sure you are NOT running in 'Live Reload' mode when testing a feature like this. Live Reload will result in this same error message which is clearly misleading. After building w/o live reload everything worked fine for me using the file:/ OR cdv:/ path.

Upvotes: 16

Nico Westerdale
Nico Westerdale

Reputation: 2186

OK finally got a workaround, which is to convert the file:/// URI to a cdvfile:// URI, which my page only complains is a mixed content warning, and does allow me to access!

function getFileEntry(imgUri) {
            window.resolveLocalFileSystemURL(imgUri, function success(fileEntry) {
                console.log("got file: " + fileEntry.fullPath);
                console.log('cdvfile URI: ' + fileEntry.toInternalURL());
                $('#imgPreview').attr("src", fileEntry.toInternalURL());
            });
        }

Would still be nice to have a proper way to access file:/// URIs, I can see cases where this wouldn't work, but for what I'm doing this is resolved.

Upvotes: 19

Related Questions