I'm using ionic2: I want to upload an image from the gallery, crop it and send it to a server.
uploadImage(): Promise<any> {
var status = 'upload';
return new Promise(resolve =>
{
const options: CameraOptions = {
quality: 100,
sourceType: 2,
destinationType: this.camera.DestinationType.DATA_URL,
mediaType: this.camera.MediaType.PICTURE,
allowEdit: true
}
this.camera.getPicture(options).then((imageData) => {
// imageData is either a base64 encoded string or a file URI
// If it's base64:
this.base64Image = "data:image/jpeg;base64",imageData;
console.log("imaaage ",this.base64Image);
resolve(this.base64Image);
}, (err) => {
console.log("error")
});
});
}
the problem is that: I want destinationType to be FILE_URL to send it, at the same time I want it to be DATA_URL to display it to the user.
what should I do to solve this problem?
Related
I want to post multipart form data, for this, we can do like this:
let formData = new FormData()
formData.append('myfile', 'your blob')
this.http.post(url, formData)
But I don't know how to convert a camera image to the blob. I am using native camera plugin and here my code:
cameraOptions: CameraOptions = {
quality: 20,
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY
}
constructor(public camera: Camera){}
takePhoto() {
return new Promise(resolve => {
this.camera.getPicture(this.cameraOptions).then((imageData) => {
resolve(imageData);
}, (err) => {
resolve(err);
});
});
}
I tried this code for blob:
dataURLtoBlob(dataURL) {
debugger;
// convert base64/URLEncoded data component to raw binary data held in a string
let byteString: string;
if (dataURL.split(',')[0].indexOf('base64') >= 0) {
byteString = atob(dataURL.split(',')[1]);
} else {
byteString = unescape(dataURL.split(',')[1]);
}
// separate out the mime component
let mimeString = dataURL
.split(',')[0]
.split(':')[1]
.split(';')[0];
// write the bytes of the string to a typed array
let ia = new Uint8Array(byteString.length);
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
let blobImg = new Blob([ia], { type: mimeString });
console.log(blobImg);
this.blobImage = blobImg;
}
With this code, I am able to get image data but how to convert in a blob,
please help...
Hello #sergey-rudenko here my output
getPicture output:
imageDataURI: content://com.android.providers.media.documents/document/image%3A78702
this.file.resolveLocalFilesystemUrl output:
entry:
FileEntry {isFile: true, isDirectory: false, name: "image:78702", fullPath: "/com.android.providers.media.documents/document/image:78702", filesystem: FileSystem, …}
filesystem: FileSystem {name: "content", root: DirectoryEntry}
fullPath: "/com.android.providers.media.documents/document/image:78702"
isDirectory: false
isFile: true
name: "image:78702"
nativeURL: "content://com.android.providers.media.documents/document/image%3A78702"
__proto__: Entry
entry.file output:
file:
File {name: "content", localURL: "cdvfile://localhost/content/com.android.providers.media.documents/document/image%3A78702", type: "image/jpeg", lastModified: 1588099237000, lastModifiedDate: 1588099237000, …}
end: 79807
lastModified: 1588099237000
lastModifiedDate: 1588099237000
localURL: "cdvfile://localhost/content/com.android.providers.media.documents/document/image%3A78702"
name: "content"
size: 79807
start: 0
type: "image/jpeg"
__proto__: Object
const blob output:
Blob {size: 79807, type: "image/jpeg"}
size: 79807
type: "image/jpeg"
__proto__: Blob
formData output:
FormData {}
__proto__: FormData
append: ƒ append()
arguments: (...)
caller: (...)
length: 2
name: "append"
__proto__: ƒ ()
[[Scopes]]: Scopes[0]
delete: ƒ delete()
entries: ƒ entries()
forEach: ƒ forEach()
get: ƒ ()
getAll: ƒ getAll()
has: ƒ has()
keys: ƒ keys()
set: ƒ ()
values: ƒ values()
constructor: ƒ FormData()
Symbol(Symbol.iterator): ƒ entries()
Symbol(Symbol.toStringTag): "FormData"
__proto__: Object
In order to obtain the blob you need a few things:
First, make sure that the options of Camera plugin are set to return FILE_URI (URL to the binary file of the image):
options: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI, // set to FILE_URI
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE
};
Second, since FILE_URI is just a link and not actual file, you need a way to obtain it. You can do that using File plugin:
// Import it:
import {File, FileEntry} from '#ionic-native/file/ngx';
// Then use it in the method that Camera plugin has for taking pictures:
getPicture() {
this.camera.getPicture(this.options).then((imageDataURI) => {
this.file.resolveLocalFilesystemUrl(imageDataURI).then((entry: FileEntry) =>
{
entry.file(file => {
console.log(file);
this.readFile(file);
});
});
}, (err) => {
// Handle error
});
};
Lastly to send it to your server, you need to read the file:
read(file) {
const reader = new FileReader();
reader.onload = () => {
const blob = new Blob([reader.result], {
type: file.type
});
const formData = new FormData();
formData.append('name', 'MyImageBlob');
formData.append('file', blob, file.name);
this.service.upload(formData).subscribe(response => {
console.log(response);
});
};
reader.readAsArrayBuffer(file);
};
Let me know if you can take it from here.
The photo I took using the application camera appears as a black screen. I looked at the other questions and tried some of the answers, but I can't translate the picture to base64. Could you help?
You can see the entire code from the link.
https://pastebin.ubuntu.com/p/4FwYdk5fvD/
takePicture(sourceType: PictureSourceType)
{
var options: CameraOptions = {
quality: 100,
sourceType: sourceType,
saveToPhotoAlbum: false,
correctOrientation: true
};
this.camera.getPicture(options).then(imagePath => {
if (this.plt.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());
}
});
}
i sorta had the same issue. I also wanted the name (not the path though), and i also wanted a base 64... so what i did what this:
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) => {
this.imgService.convertFilePathToBlob(imageData).subscribe(blob => {
this.image = blob;
});
let correctPath = imageData; // or subStr the parts you want
let currentName = this.image[1]; // grab the name
let currentImage = this.image[0]; // the image itself as base64
}).catch((err) => {
console.warn("takePicture Error: " + err);
});}
and the convert function... remember to import File, FileEntry from '#ionic-native/file/ngx'
convertFilePathToBlob(filePath:string) {
return from(this.file.resolveLocalFilesystemUrl(filePath)).pipe(
mergeMap((fileEntry: FileEntry) => {
return Observable.create(observer => {
fileEntry.file(file => {
const reader = new FileReader();
reader.onloadend = () => {
const imgBlob = new Blob([reader.result], { type: file.type });
observer.next([imgBlob, file.name]); // the name can be grabbed now
observer.complete();
};
reader.readAsArrayBuffer(file);
}, error => {
observer.error(error);
});
});
}));}
This works in my case, but i find it insane i had to do all this, and it took some debugging and googling... i hope it helps you in some way... :)
We need to load photos from camera or library(photo-gallery) and upload it.
In Android device working fine but iOS has a below error:
TypeError: Object(WEBPACK_IMPORTED_MODULE_1__ionic_native_core["cordova"]) is not a function. (In 'Object(WEBPACK_IMPORTED_MODULE_1__ionic_native_core["cordova"])(this, "getPicture", { "callbackOrder": "reverse" }, arguments)', 'Object(WEBPACK_IMPORTED_MODULE_1__ionic_native_core["cordova"])' is an instance of Object)
Also, For more details see attached screenshot.
enter image description here
Code:
if(sourceType=='library') {
const Liboptions: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
sourceType:0,
saveToPhotoAlbum:true,
targetWidth:1024,
targetHeight:720,
allowEdit:true
}
this.camera.getPicture(Liboptions).then((imagePath) => {
// Special handling for Android library
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.');
});
} else {
const CamOptions: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
sourceType: this.camera.PictureSourceType.CAMERA,
targetWidth:1024,
targetHeight:720
}
//options.popoverOptions = CameraPopoverOption; options.correctOrientation = true;
this.camera.getPicture(CamOptions).then((imagePath) => {
// Special handling for Android library
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.');
});
}
you need to add this line in your config file in ios platform
<config-file parent="NSCameraUsageDescription" platform="ios" target="*-Info.plist">
<string>You can take photos</string>
</config-file>
I have a HomePage and in ionViewWillEnter() I have added camera code. So that when HomePage get trigger it opens the Camera first
I want to customize the back button behavior that when I press the back button, after opening the camera it should navigate to SecondPage,by default it is navigating to HomePage.
ionViewWillEnter() {
this.captureVideo();
}
captureVideo() {
platform.registerBackButtonAction(() => {
this.navCtrl.push(SecondPage)
});
let options: CaptureVideoOptions = { limit: 1 };
this.mediaCapture.captureVideo(options)
.then((videodata: MediaFile[]) => {
var i, path, len;
for (i = 0, len = videodata.length; i < len; i += 1) {
path = videodata[i].fullPath;
}
this.flag_play = false;
this.flag_upload = false;
this.file.resolveLocalFilesystemUrl(path).then((newUrl) => {
alert(JSON.stringify(newUrl))
let dirPath = newUrl.nativeURL;
let dirPathSegments = dirPath.split('/')
dirPathSegments.pop()
dirPath = dirPathSegments.join('/')
this.file.readAsArrayBuffer(dirPath, newUrl.name).then(async (buffer)
=> {
await this.upload(buffer, newUrl.name);
})
})
})
.then(() => {
var videoFileName = 'video-name-here';
this.videoEditor.createThumbnail(
{
fileUri:'abc',// this.videoId,
outputFileName: videoFileName,
atTime: 2,
width: 320,
height: 480,
quality: 100
}
).then(result => {
this.result = result;
this.base64.encodeFile(result).then((base64File) => {
this.base64Thumbnail = base64File.replace("*;charset=utf-8", "jpg")
}, err => {
alert("Unable to create thumbnail")
})
})
})
}
The hardware back button works as default behaviour of cancel ...so to customize it put your specific code in the error...
takePicture(){
this.camera.getPicture({
destinationType: this.camera.DestinationType.DATA_URL,
targetWidth: 1000,
targetHeight: 1000
}).then((imageData) => {
// imageData is a base64 encoded string
this.base64Image = "data:image/jpeg;base64," + imageData;
}, (err) => {
this.navCtrl.pop();
});
}
}
I am having a problem taking a picture and uploading it to an S3 bucket when using FILE_URI for the camera.DestinationType. When using this same process with the DATA_URL DestinationType it works fine.
When using FILE_URI the file that gets uploaded to the S3 bucket says it's corrupt. I did notice the file size is much smaller (~100B) than an actual image.
Here are the versions I am using:
Ionic Framework 3.9.2 and cordova-plugin-camera 4.0.2
Here is the code I'm using:
const options: CameraOptions = {
quality: 100,
correctOrientation: true,
destinationType: this.camera.DestinationType.FILE_URI,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
sourceType: this.camera.PictureSourceType.CAMERA,
}
this.camera.getPicture(options).then((imageData) => {
console.log(imageData);
let base64data = 'data:image/jpeg;base64,' + imageData;
this.bigImg = base64data;
// imageData is either a base64 encoded string or a file URI
// If it's base64:
this.selectedPhoto = this.dataURItoBlob(this.bigImg);
}, (err) => {
// Handle error
console.log("Get Image Error: " + err);
});
this.sub = AWS.config.credentials.identityId;
let uploadMessage = "Uploading Image...";
let photoName = "testPic";
this.upload(this.selectedPhoto, uploadMessage, photoName)
.then(data => {
// Change active page to list
this.navCtrl.setRoot(TabsPage).then(() => {
});
});
dataURItoBlob(dataURI) {
// code adapted from: http://stackoverflow.com/questions/33486352/cant-upload-image-to-aws-s3-from-ionic-camera
let binary = atob(dataURI.split(',')[1]);
let array = [];
for (let i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], {type: 'image/jpeg'});
};
upload(selectedPhoto, uploadMessage, photoName) {
return new Promise((resolve, reject) => {
let loading = this.loadingCtrl.create({
content: uploadMessage
});
loading.present();
if (selectedPhoto) {
this.s3.upload({
'Key': 'protected/' + this.sub + '/' + photoName,
'Body': selectedPhoto,
'ContentType': 'image/jpeg'
}).promise().then((data) => {
this.data2 = data;
console.log('upload complete:', JSON.stringify(data));
loading.dismiss();
resolve(data);
}, err => {
console.log('upload failed....', JSON.stringify(err));
loading.dismiss();
reject(err);
});
} else {
loading.dismiss();
reject("upload failed");
}
});