I'm trying to get the content of an image in a base64 string.
Originally I was doing it with readAsDataURL
but because I want to validate the mimetype
on the client side, it seems I have to use readAsArrayBuffer as also pointed out on this site.
So prevoiusly I had this working fine:
var reader = new FileReader();
reader.onloadend = function(event) {
var base64 = reader.result;
};
reader.readAsDataURL(event.target.files[0]);
Reproduction online
Now I added the mimetype validation and I have the following:
var reader = new FileReader();
reader.onloadend = function(event) {
var realMimeType = getRealMimeType(reader);
if (realMimeType !== 'unknown') {
var emptyBufferArray = reader.result; //nothing
}else{
alert("Invalid mime type!");
}
};
reader.readAsArrayBuffer(event.target.files[0]); //<-- notice the difference
Reproduction online (not getting the base64 string)
The FileReader interface's readAsArrayBuffer () method is used to start reading the contents of a specified Blob or File. When the read operation is finished, the readyState becomes DONE, and the loadend is triggered. At that time, the result attribute contains an ArrayBuffer representing the file's data.
In this solution, however, we would be using Javascript’s FileReader API that allows us to read the content of image files and handle those files in base64 format. Regardless of the backend language being used, base64 encoded images can be decoded on the server and stored locally in the filesystem (or on cloud storage).
The readAsDataURL () method takes in a File or Blob and produces a data URL. This is basically a base64 encoded string of the file data. You can use this data URL for things like setting the src property for an image. We will look at how to do this later in the images demo. The readAsBinaryString () method can be used to read any type of file.
The Blob.arrayBuffer () method is a newer promise-based API to read a file as an array buffer. The Blob or File from which to read. The definition of 'FileReader.readAsArrayBuffer' in that specification. The compatibility table on this page is generated from structured data.
The only way I found of doing it was to use two different FileReader
instances, one inside the other.
Reproduction online
Javascript
$(document).on('change', '#upload', addBackgroundImage);
function addBackgroundImage(event) {
var reader = new FileReader();
var readerBase64 = new FileReader();
var image = event.target.files[0];
reader.onloadend = function() {
var realMimeType = getRealMimeType(reader);
if (realMimeType !== 'unknown') {
readerBase64.readAsDataURL(image);
} else {
alert("Please upload a valid image file");
}
};
reader.readAsArrayBuffer(image);
readerBase64.onloadend = function(){
var base64 = this.result;
$('.bg').css('background-image', 'url('+base64+')');
};
$('#upload').val('');
}
function getRealMimeType(reader){
var arr = (new Uint8Array(reader.result)).subarray(0, 4);
var header = '';
var realMimeType;
for (var i = 0; i < arr.length; i++) {
header += arr[i].toString(16);
}
// magic numbers: http://www.garykessler.net/library/file_sigs.html
switch (header) {
case "89504e47":
realMimeType = "image/png";
break;
case "47494638":
realMimeType = "image/gif";
break;
case "ffd8ffDB":
case "ffd8ffe0":
case "ffd8ffe1":
case "ffd8ffe2":
case "ffd8ffe3":
case "ffd8ffe8":
realMimeType = "image/jpeg";
break;
default:
realMimeType = "unknown"; // Or you can use the blob.type as fallback
break;
}
return realMimeType;
}
HTML
<input type="file" id="upload" />
<div class="bg"></div>
You can try this "stolen" function:
function arrayBufferToBase64(buffer) {
let binary = '';
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With