Reputation: 2186
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
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
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
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
Reputation: 31
This is the only thing that worked for me: window['Ionic']['WebView'].convertFileSrc(yourURL);
Upvotes: 2
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
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
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
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
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
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