I am using ionic 3 android build apk and trying to laod image from file:///storage/emulated/0/data/io.ionic.vdeovalet/cache/image.jpeg
takePicture(sourceType) {
try {
// Create options for the Camera Dialog
var options = {
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI,
encodingType: this.camera.EncodingType.JPEG,
sourceType: sourceType,
};
this.camera.getPicture(options).then((imagePath) => {
// Special handling for Android library
if (this.platform.is('android') && sourceType ===
this.camera.PictureSourceType.PHOTOLIBRARY) {
this.filePath.resolveNativePath(imagePath)
.then(filePath => {
let correctPath = filePath.substr(0, filePath.lastIndexOf('/') + 1);
let currentName = imagePath.substring(imagePath.lastIndexOf('/') + 1,
imagePath.lastIndexOf('?'));
this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
this.lastImage = filePath;
});
} else {
var currentName = imagePath.substr(imagePath.lastIndexOf('/') + 1);
var correctPath = imagePath.substr(0, imagePath.lastIndexOf('/') + 1);
this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
}
}, (err) => {
this.presentToast('Error while selecting image.');
});
} catch (e) {
console.error(e);
}
}
Error: Not allowed to load local resource
android 6.0.1
No Need To Downgrade just write this code.
private win: any = window;
this.win.Ionic.WebView.convertFileSrc(path);
I had the same issues and it turns out that
The new ionic webview plugin is the cause for the problem.
The new plugin: cordova-plugin-ionic-webview # 2.x seem unstable...
to get it working downgraded back to cordova-plugin-ionic-webview#1.2.1 and all should work
Steps:
1. uninstall webview
ionic cordova plugins rm cordova-plugin-ionic-webview
2. install old one:
ionic cordova plugins add cordova-plugin-ionic-webview#1.2.1
3. clean cordova
cordova clean android
When Ionic is used with Capacitor, we can get the correct path of an image or other resource on a native device by:
import { Capacitor } from '#capacitor/core';
Capacitor.convertFileSrc(filePath);
https://ionicframework.com/docs/core-concepts/webview
The only thing that worked for me was convertFileSrc()
let win: any = window;
let safeURL = win.Ionic.WebView.convertFileSrc(this.file.dataDirectory+'data/yourFile.png');
Hope this helps
Try This:
1) https://devdactic.com/ionic-2-images/
In this tutorial, ionic 2 & ionic 3 is the best way to upload and upload images.
2) https://devdactic.com/ionic-4-image-upload-storage/ In this tutorial, ionic 4 is the best way to upload and upload images.
i also use these... and it working fine...
And I have also faced the problem of
not allowed to load local resource
You can see here :
#ionic/angular 4.0.0-beta.13 : Not allowed to load local resource : with webview 2.2.3 - Ionic CLI 4.3.1
Try this:
const options: CameraOptions = {
quality: 10
, destinationType: this.camera.DestinationType.DATA_URL
, mediaType: this.camera.MediaType.PICTURE
// Optional , correctOrientation: true
, sourceType: sourceType == 0 ? this.camera.PictureSourceType.CAMERA : this.camera.PictureSourceType.PHOTOLIBRARY
// Optional , saveToPhotoAlbum: true
};
this.camera.getPicture(options).then(imageBase64 => {
let txtForImage = `data:image/jpeg;base64,` + imageBase64;
this.imageToLoad = txtForImage;
})
.catch(error => {
alert("Error: " + error);
console.error(error);
});
Copy this line into your index.html
<meta http-equiv="Content-Security-Policy" content="default-src *;
style-src 'self' 'unsafe-inline';
script-src 'self' 'unsafe-inline' 'unsafe-eval';
img-src 'self' data: https://s-media-cache-ak0.pinimg.com;
script-src 'self' https://maps.googleapis.com;" />
Then, write this function instead of your one, note that what this script does is returning the photo as base64
getImageFromCamera() {
const options: CameraOptions = {
quality: 20,
saveToPhotoAlbum: true,
destinationType: this.camera.DestinationType.FILE_URI,
sourceType: this.camera.PictureSourceType.CAMERA,
encodingType: this.camera.EncodingType.JPEG,
allowEdit: false
};
this.camera.getPicture(options).then((imageData) => {
this.imageURI = imageData;
this.imageName = imageData.substr(imageData.lastIndexOf('/') + 1);
// Create a folder in memory location
this.file.checkDir(this.file.externalRootDirectory, 'Demo')
.then(() => {
this.fileCreated = true;
}, (err) => {
console.log("checkDir: Error");
this.presentToast("checkDir Failed");
});
if (this.fileCreated) {
this.presentToast("Directory Already exist");
}
else {
this.file.createDir(this.file.externalRootDirectory, "Demo", true)
.then((res) => {
this.presentToast("Directory Created");
}, (err) => {
console.log("Directory Creation Error:");
});
}
//FILE MOVE CODE
let tempPath = this.imageURI.substr(0, this.imageURI.lastIndexOf('/') + 1);
let androidPath = this.file.externalRootDirectory + '/Bexel/';
this.imageString = androidPath + this.imageName;
this.file.moveFile(tempPath, this.imageName, androidPath, this.imageName)
.then((res) => {
this.presentToast("Image Saved Successfully");
this.readImage(this.imageString);
}, (err) => {
console.log("Image Copy Failed");
this.presentToast("Image Copy Failed");
});
//Complete File Move Code
this.toDataURL(this.imageURI, function (dataUrl) {
console.log('RESULT:' + dataUrl);
});
}, (err) => {
console.log(JSON.stringify(err));
this.presentToast(JSON.stringify(err));
});
}
presentToast(msg) {
let toast = this.toastCtrl.create({
message: msg,
duration: 2000
});
toast.present();
}
toDataURL(url, callback) {
let xhr = new XMLHttpRequest();
xhr.onload = function () {
let reader = new FileReader();
reader.onloadend = function () {
callback(reader.result);
};
reader.readAsDataURL(xhr.response);
};
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.send();
}
readImage(filePath) {
let tempPath = filePath.substr(0, filePath.lastIndexOf('/') + 1);
let imageName = filePath.substr(filePath.lastIndexOf('/') + 1);
this.file.readAsDataURL(tempPath, imageName)
.then((res) => {
this.presentToast("Image Get Done");
this.imageUrl = res;
}, (err) => {
this.presentToast("Image Get Error");
});
}
It sees like it's an issue with content CSP (content security policy), the meta tag should fix this issue, then the code will read the photo as base64, then here you go, in HTML:
<img [src]="imageUrl">
And you can modify the function to remove unnecessary console.log, i was just testing.
All I had to do was use the proper Imagepicker Options, the output type did it:
const options: ImagePickerOptions = {
maximumImagesCount: 1,
outputType: 1,
quality: 50
};
let win: any = window; // hack ionic/angular compilator
var myURL = win.Ionic.WebView.convertFileSrc(myURL);
Related
I am building a cordova application and I need to retrieve a blob from an image file and use that as the src of an img tag. Right now the image is stored locally, but will be pulled from a database in the future. Everything is working as expected, but the source of the image is not being set when I use URL.createObjectURL(blob), it seems the url is corrupt.
Here is my code:
takePicture() {
// eslint-disable-next-line no-undef
const srcType = Camera.PictureSourceType.CAMERA;
const options = {
// Some common settings are 20, 50, and 100
quality: 10,
// eslint-disable-next-line no-undef
destinationType: Camera.DestinationType.FILE_URI,
// In this app, dynamically set the picture source, Camera or photo gallery
sourceType: srcType,
// eslint-disable-next-line no-undef
encodingType: Camera.EncodingType.PNG,
// eslint-disable-next-line no-undef
mediaType: Camera.MediaType.PICTURE,
allowEdit: true,
correctOrientation: true, //Corrects Android orientation quirks
};
navigator.camera.getPicture(
function cameraSuccess(imageUri) {
window.resolveLocalFileSystemURL(
imageUri,
function success(fileEntry) {
fileEntry.file(
function(file) {
const reader = new FileReader();
reader.onloadend = function() {
const blob = new Blob([new Uint8Array(this.result)], { type: 'image/png' });
const elem = document.getElementById('img');
elem.src = URL.createObjectURL(blob);
};
reader.readAsArrayBuffer(file);
},
function(e) {
alert(e);
}
);
},
function() {}
);
},
function cameraError(error) {
alert('Unable to obtain picture: ' + error, 'app');
},
options
);
If I remove this line of code: elem.src = URL.createObjectURL(blob);
And replace it with this: elem.src = imageUri;
Everything works fine, so I know the image is being saved correctly. Is it possible that the image is to large, and therefore being rejected?
OK, after doing some more troubleshooting, I figured out the problem was the tag was missing the img-src directive. To fix this I simply added img-src '*' data: blob: ; to the tag, and everything is working.
Note: Just adding '*' did not work. I also had to add blob: as well
I'm working on an ionic3 application. I need to take an image from the user either by camera or gallery, first saves it to the local directory then upload the image to the server. I used the following step by step tutorial: https://devdactic.com/ionic-2-images/
Uploading the photo is working like a charm, but while saving the image to the local directory and save the path on local storage, after retrieving from storage it shows the following error: .
As it's obvious it complains about Not allowed to load local resource.
Next, I started to google for the solution, and I found this solution in StackOverflow and this in GitHub. As they both suggested, the problem is with cordova-plugin-ionic-webview, so I need to downgrade the version. When I tried their solution, the uploading and showing the image to the user is working perfectly, however, it creates problem other parts of the application which is loading data from asset no matter what; images, fonts. Shows the following error .Next I found a solutionf for the problem in GitHub here, as it suggested and accepted by most users we need to use the latest version of **cordova-plugin-ionic-webview **, which of course it would cause the first problem for me.
I'm gonna upload the codes here as well.`
getImage() {
this.presentActionSheet();
} //end getImage
public uploadImage() {
console.log('Uploading the image');
console.log(this.lastImageL);
var targetPath = this.pathForImage(this.lastImage);
console.log(targetPath);
var url = "https://dev.raihan.pomdev.net/wp-json/raihan/v1/profilePhoto";
var filename = this.lastImage;
console.log(' targetPath : ', targetPath);
console.log('File Name : ', filename)
console.log(url, " IS the URL");
var options = {
fileKey: "image",
fileName: filename,
chunkedMode: false,
mimeType: "multipart/form-data",
params: {
'image': filename,
'user_id': 79
}
};
const fileTransfer: TransferObject = this.transfer.create();
this.loading = this.loadingCtrl.create({
content: 'منتظر باشید',
});
this.loading.present();
// Use the FileTransfer to upload the image
fileTransfer.upload(targetPath, url, options).then(data => {
this.loading.dismissAll()
this.presentToast(' . عکس شما موفقانه ذخیره شد');
this.storage.set("Profile_Photo", targetPath).then((data) => {
console.log('response of uploading the image ', data);
console.log('Target Path ', targetPath);
console.log('In set storage ', targetPath);
$("#Photo").attr("src", targetPath);
$("#Photo2").attr("src", targetPath);
console.log('myphoto ', targetPath);
});
}, err => {
this.loading.dismissAll()
this.presentToast('مشکلی در قسمت ذخیره کردن عکس شما وجود دارد ' + err);
console.log('error sending the image');
console.log(err);
});
}
public takePicture(sourceType) {
var options = {
quality: 100,
sourceType: sourceType,
saveToPhotoAlbum: false,
correctOrientation: true
};
// Get the data of an image
this.camera.getPicture(options).then((imagePath) => {
if (this.platform.is('android') && sourceType === this.camera.PictureSourceType.PHOTOLIBRARY) {
this.filePath.resolveNativePath(imagePath)
.then(filePath => {
let correctPath = filePath.substr(0, filePath.lastIndexOf('/') + 1);
let currentName = imagePath.substring(imagePath.lastIndexOf('/') + 1, imagePath.lastIndexOf('?'));
this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
});
} else {
var currentName = imagePath.substr(imagePath.lastIndexOf('/') + 1);
var correctPath = imagePath.substr(0, imagePath.lastIndexOf('/') + 1);
this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
}
}, (err) => {
this.presentToast('Error while selecting image.');
});
}
ionViewDidLoad() {
console.log('ionViewDidLoad CaptureImagePage');
}
private createFileName() {
var d = new Date(),
n = d.getTime(),
newFileName = n + ".jpg";
return newFileName;
}
// Copy the image to a local folder
private copyFileToLocalDir(namePath, currentName, newFileName) {
this.file.copyFile(namePath, currentName, cordova.file.dataDirectory, newFileName).then(success => {
this.lastImage = newFileName;
this.uploadImage();
}, error => {
this.presentToast('Error while storing file. ' + error);
});
}
private presentToast(text) {
let toast = this.toastCtrl.create({
message: text,
duration: 5000,
position: 'center'
});
toast.present();
}
// Always get the accurate path to your apps folder
public pathForImage(img) {
if (img === null) {
return '';
} else {
return cordova.file.dataDirectory + img;
}
}
public presentActionSheet() {
let actionSheet = this.actionSheetCtrl.create({
title: 'Select Image Source',
buttons: [
{
text: 'Load from Library',
handler: () => {
this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY);
}
},
{
text: 'Use Camera',
handler: () => {
this.takePicture(this.camera.PictureSourceType.CAMERA);
}
},
{
text: 'Cancel',
role: 'cancel'
}
]
});
actionSheet.present();
}
`
Now I'm confused which version of **cordova-plugin-ionic-webview ** I should use? Is there someone who could help me?
Note: Thanks for your patience to read all the questions.
I would try to use the latest version of the WebView if possible, and then use the window.Ionic.WebView.convertFileSrc() method on the file:/// path before putting it on a page for display. Those tips can be seen here:
https://ionicframework.com/docs/building/webview
Cordova and Capacitor apps are hosted on a local HTTP server and are
served with the http:// protocol. Some plugins, however, attempt to
access device files via the file:// protocol. To avoid difficulties
between http:// and file://, paths to device files must be rewritten
to use the local HTTP server. For example, file:///path/to/device/file
must be rewritten as http://://path/to/device/file
before being rendered in the app.
For Cordova apps, the Ionic Web View plugin provides a utility
function for converting File URIs:
window.Ionic.WebView.convertFileSrc(). There is also a corresponding
Ionic Native plugin: #ionic-native/ionic-webview.
Here is a sample method I use, which works fine in the 4.x webview:
getNormalizedUrl(path: string): SafeResourceUrl {
let newPath = this.domSanitizer.bypassSecurityTrustUrl(
window.Ionic.WebView.convertFileSrc(path));
return newPath;
}
I have developed an android application using Ionic4. I am facing some issues with Ionic Native Camera plugin. The following is my code. The issues that i am facing is given below. The version if camera plugin i am using is "#ionic-native/camera": "^5.3.0",.
Issues
Gallery is not opening
Captured image is not returning.
Application crashes after taking picture
html
<img [src]="studentImage!==null ? studentImage: 'assets/icon/ic_avatar.png'" class="add-picture" (click)="addImage()">
.ts
public addImage() {
this.genericServices.presentActionSheet(this.openGallery, this.openCamera);
}
private openCamera = () => {
this.studentImage = this.genericServices.selectPicture('camera');
console.log('Captured Image:=>' + this.studentImage);
}
private openGallery() {
this.studentImage = this.genericServices.selectPicture('gallery');
}
service
public async selectPicture(source) {
let base64Image = null;
const cameraOptions: CameraOptions = {
quality: 75,
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.PNG,
mediaType: this.camera.MediaType.PICTURE,
sourceType: source === 'camera' ? this.camera.PictureSourceType.CAMERA : this.camera.PictureSourceType.PHOTOLIBRARY,
correctOrientation: true
};
await this.camera.getPicture(cameraOptions).then((imageData) => {
console.log('Returned Image=>' + base64Image);
return base64Image = 'data:image/jpeg;base64,' + imageData;
}).catch(() => {
});
}
Hard to say what your problem is. I would probably write the code slightly different, like this:
async selectImage() {
const actionSheet = await this.actionCtrl.create({
header: "Select Image source",
buttons: [{
text: 'Load from Library',
handler: () => {
this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY);
}
},
{
text: 'Use Camera',
handler: () => {
this.takePicture(this.camera.PictureSourceType.CAMERA);
}
},
{
text: 'Cancel',
role: 'cancel'
}
]
});
await actionSheet.present();
}
And then in the takePicture() method decide what destinationType should be, default is FILE_URI (1).
takePicture(sourceType: PictureSourceType) {
var options: CameraOptions = {
quality: 80,
sourceType: sourceType,
saveToPhotoAlbum: false,
correctOrientation: true,
destinationType: 1,
targetWidth: 1240,
targetHeight: 768,
};
this.camera.getPicture(options)
.then((imageData) => {
// do something with the imageData, should be able to bind it to a variable and
// show it in your html file. You might need to fix file path,
// remember to import private win: any = window, and use it like this.
this.imagePreview = this.win.Ionic.WebView.convertFileSrc(imageData);
}).catch((err) => {
console.warn("takePicture Error: " + err);
});
}
This should work fine... i just tested it. But as i said, there could be several things wrong with your setup. Hope it helps in one way or another... otherwise create a fiddle, and i will gladly look at the code for you.
I have the error like in question, when I'm trying to design my application to call native.camera, I see my console in ionic 3 project, I saw this error :
Native : tried calling Camera.getPicture, but Cordova is not available. Make sure to include cordova.js or run in a device / simulator.
Here is the code that I used to called native camera.
This is the code in my problem.html
<button class="logoCamera" ion-button (click)="presentActionSheet()">
<ion-icon name="camera" ></ion-icon>
This is the code in my problem.ts
import { File } from '#ionic-native/file';
import { Transfer, TransferObject} from '#ionic-native/transfer';
import { FilePath } from '#ionic-native/file-path';
import { Camera } from '#ionic-native/camera';
public presentActionSheet(){
let actionSheet = this.actionSheetCtrl.create({
title: 'Select Image',
buttons: [
{
text: 'Load from Library',
handler: () => {
this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY);
}
},
{
text: 'Use Camera',
handler: () => {
this.takePicture(this.camera.PictureSourceType.CAMERA);
}
},
{
text: 'Cancel',
role: 'cancel'
}
]
});
actionSheet.present();
}
public takePicture(sourceType){
//Create option for the Camera dialog
var options = {
quality: 100,
sourceType : sourceType,
saveToPhotoAlbum: false,
correctOrientation: true
};
//Get the data of an image
this.camera.getPicture(options).then((imagePath) => {
//special handling for android lib
if(this.platform.is('android') && sourceType === this.camera.PictureSourceType.PHOTOLIBRARY) {
this.filePath.resolveNativePath(imagePath)
.then(filePath => {
let correctPath = filePath.substr(0, filePath.lastIndexOf('/') + 1 );
let currentName = imagePath.substring(imagePath.lastIndexOf('/') + 1, imagePath.lastIndexOf('?'));
this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
});
} else {
var currentName = imagePath.substr(imagePath.lastIndexOf('/') + 1);
var correctPath = imagePath.substr(0, imagePath.lastIndexOf('/')+ 1);
this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
}
}, (err) => {
this.presentToast('Error while selecting Image.');
});
}
//Create a new name for image
private createFileName() {
var d = new Date(),
n = d.getTime(),
newFileName = n + ".jpg";
return newFileName;
}
//copy image to local folder
private copyFileToLocalDir(namePath, currentName, newFileName) {
this.file.copyFile(namePath, currentName, cordova.file.dataDirectory, newFileName).then(success => {
this.lastImage = newFileName;
}, error => {
this.presentToast('Error while storing file.');
});
}
private presentToast(text) {
let toast = this.toastCtrl.create({
message: text,
duration: 3000,
position: 'middle'
});
toast.present();
}
public pathForImage(img){
if (img === null) {
return '';
} else {
return cordova.file.dataDirectory + img;
}
}
public uploadImage() {
//destination URL
var url = "";
//file to upload
var targetPath = this.pathForImage(this.lastImage);
//file name only
var filename = this.lastImage;
var options = {
fileKey: "file",
fileName: filename,
chunkedMode: false,
mimeType: "multipart/form-data",
params: {'fileName': filename}
};
const fileTransfer: TransferObject = this.transfer.create();
this.loading = this.loadingCtrl.create({
content: 'Uploading...',
});
this.loading.present();
//use FileTransfer to upload image
fileTransfer.upload(targetPath, url, options).then(data => {
this.loading.dismissAll()
this.presentToast('Image successful uploaded.');
}, err => {
this.loading.dismissAll()
this.presentToast('Error while uploading file.');
});
}
When I run ionic serve, everything is smooth, no error, no nothing.
But when I click my button to access natve camera, the error shows, please help me figure out the problem, I check a lot of web, and none of it solve my question.
After I try run ionic cordova run ios --simulator, there are error coming out, but I am pretty sure that this error does not exist before I run this command.
May I know how to solve this problem ??
The error message is pretty accurate here:
Native : tried calling Camera.getPicture, but Cordova is not available. Make sure to include cordova.js or run in a device / simulator.
Running ionic serve does not include cordova.js nor does it run your application in a simulator or on a device which is why you get the error. You can fix it either by running your application on the device or simulator:
ionic cordova run android/ios --device/--simulator
Or by adding the browser platform:
cordova platform add browser
And running the browser platform:
ionic cordova run browser
I am using Camera plugin in Ionic 2 for uploading photos. I am running the app on an Android device. The Carema capture is displayed in the app but when selected from Gallery the photo is not displayed.
The following methods are used for Camera and Gallary:
private openCamera(){
var options: CameraOptions = {
sourceType: this.camera.PictureSourceType.CAMERA,
destinationType: this.camera.DestinationType.DATA_URL,
allowEdit: true,
saveToPhotoAlbum: true
};
this.camera.getPicture(options).then((imageData) => {
this.cameraData = 'data:image/jpeg;base64,' + imageData;
this.photoTaken = true;
this.photoSelected = false;
let base64Image = 'data:image/jpeg;base64,' + imageData;
}, (err) => {
// Handle error
});
}
private selectFromGallery() {
var options = {
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
destinationType: this.camera.DestinationType.FILE_URI
};
this.camera.getPicture(options).then((imageData) => {
this.cameraUrl = imageData;
this.photoSelected = true;
this.photoTaken = false;
}, (err) => {
// Handle error
});
}
Following is the code to display in HTML page:
<img [src]="cameraData" *ngIf="photoTaken">
<img [src]="cameraUrl" *ngIf="photoSelected">
You need to use a file plugin to obtain local filesystem url when you select from library.
To install:
$ ionic cordova plugin add cordova-plugin-file
$ npm install --save #ionic-native/file
Import:
import { File } from '#ionic-native/file';
and in your code:
constructor( private file: File, .... ) {}
.....
const options: CameraOptions = {
destinationType: this.camera.DestinationType.FILE_URI,
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY
}
this.camera.getPicture(options).then((imageURI) => {
this.file.resolveLocalFilesystemUrl(imageURI).then(fileEntry => {
this.cameraUrl = fileEntry.nativeURL;
this.photoSelected = true;
this.photoTaken = false;
});
}, (err) => {
// Handle error
});
EDIT
You might need to sanitize the value for img src:
<img *ngIf="cameraUrl" [src]="sanitizeUrl(cameraUrl)" />
The function:
import { DomSanitizer } from '#angular/platform-browser';
....
constructor( private sanitizer: DomSanitizer, .... ) {}
....
sanitizeUrl(url) {
return this.sanitizer.bypassSecurityTrustUrl(url);
}