I am developing an application using phone gap. I capture image/audio/video and store its path in local storage. I need to fetch base64 of captured file and store it in the database and then sync it with server. Is that possible using javascript ?
I tried using FileReader API that phone gap provides but the function reader.onloadend() does not get executed.
Could manage to get base64 of image using a canvas but is it possible to get base64 for audio and video using canvas?
Thanks.
Yes It's possible to get the base64 of a media file
reader.onloadend() is not being called because you might have missed this line reader.readAsDataURL(file).
// here i have a file input and i am using the FileReader Api to read the content on it's change event ( i have no idea what is the event for capturing a media in phonegap
$("#file").change(function(e){
var file = e.currentTarget.files[0];
var FR = new FileReader();
FR.onload = function (encodedFile) {
//alert("onload is called.");
}
FR.onloadend = function (encodedFile) {
var src = encodedFile.target.result;
src = src.split("base64,");
// This is the base64 encoded string of that media file which you will be interested to store in the database(post to the server
var contentAsBase64EncodedString = src[1];
}
reader.readAsDataURL(file);
}
Related
I am using react-easy-crop to allow users to modify their profile pictures after uploading. The problem I am experiencing is that after cropping, the image is returned in the form of a blob url like this: blob:http://localhost:3000/5e44190e-a087-4683-b3a4-dfce4a57ee62 which is unhelpful since it can only be viewed on my local machine.
I have tried converting it to a data url (which I understand can then be shared and viewed across browsers), using FileReader and the readAsDataURL() method like this:
let blob = await fetch(imageToCrop).then((r) => r.blob());
let reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function () {
let base64data = reader.result;
console.log(base64data);
};
The base64data variable does return what I think I need, however all my attempts to then store this result in my state only return a null value.
Does anyone know what is the best way to handle this?
If you have this line in your code, delete it because it revoke your URL.
window.URL.revokeObjectURL(this.fileUrl);
If you need the base64 output of the cropped image, you can get it after using the canvas to crop it with canvas.toDataURL('image/jpeg'). This base64 string can then be shared to anyone or uploaded to a remote server.
This is basically the commented line in the getCroppedImg() function of this demo: https://codesandbox.io/s/q8q1mnr01w?file=/src/cropImage.js:2362-2562
BTW I guess you could also upload the blob to a remote server and store the image somewhere like AWS S3.
Look at my code
<img src='data:image/png;base64,{{imgSrc}}'>
In my controller
$scope.imgSrc = $scope.deviceDetail.imgSrc;
I am getting this type of response from my backend in imgSrc which is stored in mongodb.
"�PNG\r\n\u001a\n\u0000\u0000\u0000\rIHDR\u0000\u0000\u0003 \u0000\u0000\u0002R\b\u0002\u0000\u0000\u0000��6A\u0000\u0000\u0000\u0006bKGD\u0000�\u0000�\u0000�����\u0000\u0000 \u0000IDATx���{xT���W x\u0000\u0006%$F�c F\t�\"�V��\u0000�P\u000f\b���xEъ��T�z#� \u0018�諀`�TJ�Z\u0015\t�\"R��#\u000b|H�h8\u0005\......"
Now I want png image from this data,I have tried this data into base64 but still not getting image.
Please suggest me what is wrong here?
You can convert image to data base64 bit.
Base64 is a group of similar binary-to-text encoding schemes that represent
binary data in an ASCII string format by translating it into a radix-64 representation.
To convert a file to base64 (image or any other kind of file) with cordova, ionic or phonegap we will need only the cordova file plugin and 1 human eye. Then we will use the FileReader to read the the content of a file with the method readAsDataURL.
/**
* This function will handle the conversion from a file to base64 format
*
* #path string
* #callback function receives as first parameter the content of the image
*/
function getFileContentAsBase64(path,callback){
window.resolveLocalFileSystemURL(path, gotFile, fail);
function fail(e) {
alert('Cannot found requested file');
}
function gotFile(fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onloadend = function(e) {
var content = this.result;
callback(content);
};
// The most important point, use the readAsDatURL Method from the file plugin
reader.readAsDataURL(file);
});
}}
Then we will use it to convert a local image to base64 :
var path = "file://storage/0/downloads/myimage.png";
// Convert image
getFileContentAsBase64(path,function(base64Image){
//window.open(base64Image);
console.log(base64Image);
// Then you'll be able to handle the myimage.png file as base64
});
Remember that you need the file plugin from cordova, read and learn how to use it here. You can download the file plugin into your project executing in your cordova CLI :
cordova plugin add cordova-plugin-file
continue here
https://gist.github.com/HereChen/e173c64090bea2e2fa51
http://tutsheap.com/web/javascript/get-base64-image-url/
I have an HTML5/javscript app which uses
<input type="file" accept="image/*;capture=camera" onchange="gotPhoto(this)">
to capture a camera image. Because my app wants to be runnable offline, how do I save the File (https://developer.mozilla.org/en-US/docs/Web/API/File) object in local storage, such that it can be retrieved later for an ajax upload?
I'm grabbing the file object from the using ...
function gotPhoto(element) {
var file = element.files[0];
//I want to save 'file' to local storage here :-(
}
I can Stringify the object and save it, but when I restore it, it is no longer recognised as a File object, and thus can't be used to grab the file content.
I have a feeling it can't be done, but am open to suggestions.
FWIW My workaround is to read the file contents at store time and save the full contents to local storage. This works, but quickly consumes local storage since each file is a 1MB plus photograph.
You cannot serialize file API object.
Not that it helps with the specific problem, but ...
Although I haven't used this, if you look at the article it seems that there are ways (although not supported yet by most browsers) to store the offline image data to some files so as to restore them afterward when the user is online (and not to use localStorage)
Convert it to base64 and then save it.
function gotPhoto(element) {
var file = element.files[0];
var reader = new FileReader()
reader.onload = function(base64) {
localStorage["file"] = base64;
}
reader.readAsDataURL(file);
}
// Saved to localstorage
function getPhoto() {
var base64 = localStorage["file"];
var base64Parts = base64.split(",");
var fileFormat = base64Parts[0].split(";")[1];
var fileContent = base64Parts[1];
var file = new File([fileContent], "file name here", {type: fileFormat});
return file;
}
// Retreived file object
Here is a workaround that I got working with the code below. I'm aware with your edit you talked about localStorage but I wanted to share how I actually implemented that workaround. I like to put the functions on body so that even if the class is added afterwards via AJAX the "change" command will still trigger the event.
See my example here: http://jsfiddle.net/x11joex11/9g8NN/
If you run the JSFiddle example twice you will see it remembers the image.
My approach does use jQuery. This approach also demonstrates the image is actually there to prove it worked.
HTML:
<input class="classhere" type="file" name="logo" id="logo" />
<div class="imagearea"></div>
JS:
$(document).ready(function(){
//You might want to do if check to see if localstorage set for theImage here
var img = new Image();
img.src = localStorage.theImage;
$('.imagearea').html(img);
$("body").on("change",".classhere",function(){
//Equivalent of getElementById
var fileInput = $(this)[0];//returns a HTML DOM object by putting the [0] since it's really an associative array.
var file = fileInput.files[0]; //there is only '1' file since they are not multiple type.
var reader = new FileReader();
reader.onload = function(e) {
// Create a new image.
var img = new Image();
img.src = reader.result;
localStorage.theImage = reader.result; //stores the image to localStorage
$(".imagearea").html(img);
}
reader.readAsDataURL(file);//attempts to read the file in question.
});
});
This approach uses the HTML5 File System API's to read the image and put it into a new javascript img object. The key here is readAsDataURL. If you use chrome inspector you will notice the images are stored in base64 encoding.
The reader is Asynchronous, this is why it uses the callback function onload. So make sure any important code that requires the image is inside the onLoad or else you may get unexpected results.
You could use this lib:
https://github.com/carlo/jquery-base64
then do something similar to this:
//Set file
var baseFile = $.base64.encode(fileObject);
window.localStorage.setItem("file",basefile);
//get file
var outFile = window.localStorage.getItem("file");
an other solution would be using json (I prefer this method)
using: http://code.google.com/p/jquery-json/
//Set file
window.localStorage.setItem("file",$.toJSON(fileobject));
//get file
var outFile = $.evalJSON(window.localStorage.getItem("file"));
I don't think that there is a direct way to Stringify and then deserialize the string object into the object of your interest. But as a work around you can store the image paths in your local storage and load the images by retrieving the URL for the images. Advantages would be, you will never run out of storage space and you can store 1000 times more files there.. Saving an image or any other file as a string in local storage is never a wise decision..
create an object on the global scope
exp: var attmap = new Object();
after you are done with file selection, put your files in attmap variable as below,
attmap[file.name] = attachmentBody;
JSON.stringify(attmap)
Then you can send it to controller via input hidden or etc. and use it after deserializing.
(Map<String, String>)JSON.deserialize(attachments, Map<String,String>.class);
You can create your files with those values in a for loop or etc.
EncodingUtil.base64Decode(CurrentMapValue);
FYI:This solution will also cover multiple file selection
You could do something like this:
// fileObj = new File(); from file input
const buffer = Buffer.from(await new Response(fileObj).arrayBuffer());
const dataUrl = `data:${fileObj.type};base64,${buffer.toString("base64")}`;
localStorage.setItem('dataUrl', dataUrl);
then you can do:
document.getElementById('image').src = localStorage.getItem('dataUrl');
Using the filereader API it is possible to show a preview of the file, by reading the file with readAsDataURL
What I am trying to do is:
The user selects a file
A preview is shown, so that the user has some feedback.
If the user is satisfied, he submits the data to the backend.
Implementing step 3 can be done by re-reading the file with readAsBinaryString, but this looks problematic because the data could have disappeared or changed on disk. So What I would like is to convert the data returned from readAsDataURL to the format returned by readAsBinaryString. How can I do this?
Another alternative would be to submit the data to the backend as returned by readAsDataURL, but I would like to avoid that, since that would require special handling on the backend in my case.
Like CBroe said, you dont need to read the file twice.
JS :
handleFileSelectThumbFile(evt){
var files = evt.target.files;
var file = files[0];
// You can get the mime type like this.
var thumbMIME = files[0]['name'].split('.').pop();
if (files && file) {
var reader = new FileReader();
reader.onload = function(readerEvt) {
// Split the readerEvt.target.result by a ','.
// You can send the binaryString variable to the server.
// Its base64 encoded already.
var binaryString = readerEvt.target.result.split(',')[1];
// Set the image preview to the uploaded image.
$('.img-preview').prop('src', readerEvt.target.result);
}.bind(this);
reader.readAsDataURL(file);
}
}
HTML :
<input type="file" onChange={this.handleFileSelectThumbFile} required/>
<img src='http://placehold.it/300' class='img-preview'/>
You can read the MIME type from the first part of readerEvt as well. Look at CBroe's comment above.
I have a webapp that is saving images locally until they are ready to be sent to the server. When I save the images locally, I base64 encode them. Now I want to do a multipart file upload with these images.
So I need to convert the image back into binary form. I've tried using the FileReader to convert it back like this,
var fr = new FileReader();
fr.onloadend = function(binaryImage){
debugger;
binaryImage;
};
var base64Str = item.base64Image.substr(item.base64Image.indexOf("base64") + 7);
//var base64Str = item.base64Image;
fr.readAsBinaryString(base64Str);
but the onloadend event is never fired and there are no errors. Once I get the image I wont have trouble uploading it. Any ideas?
Thanks!
Not to familiar with FileReader, but I believe readAsBinaryString is expecting a Blob or File object. Passing it a string causes errors on my end. Try this:
var fr = new FileReader();
fr.onloadend = function(binaryImage){
debugger;
binaryImage;
};
var blob = new Blob([item.base64Image.
substr(item.base64Image.indexOf("base64") + 7)]);
fr.readAsBinaryString(blob);
I don't think this will give you want though. Check out this article for ways to encode/decode Base64: How can you encode to Base64 using Javascript?
Looks like you can use btoa() and atob() for web kit browsers.