Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get image base64 with reader.readAsArrayBuffer(file)

Tags:

javascript

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)

like image 649
Alvaro Avatar asked Apr 12 '16 23:04

Alvaro


People also ask

What is the use of readasarraybuffer in Java?

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.

How to read a Base64 encoded image file in JavaScript?

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).

What is the difference between readasdataurl () and readasbinarystring ()?

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.

How do I read a file as an array buffer?

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.


2 Answers

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>
like image 78
Alvaro Avatar answered Nov 14 '22 14:11

Alvaro


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);
}
like image 35
Jonatas Walker Avatar answered Nov 14 '22 13:11

Jonatas Walker