简体   繁体   中英

FileReader readAsDataURL creating large base64 images

I have a requirement to convert an input image (blob) to base64 image. Im aware the size will increase by approx 1.37.

However i have noticed when using the firereader.readAsDataUrl the size of the image is extremely large when compared to the built in base64 command line tool you have on macOS.

https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL

Steps to reproduce:

  1. Download this free sample image https://wall.alphacoders.com/big.php?i=685897 make sure to click the Download button (Downlaod Original 8000x600). Do not use right click save as because the image will be compressed

  2. Use the jsfiddle to pick the above downloaded image and check the console log for the size of the base 64. https://jsfiddle.net/b7nkw8j9/ you can see the size is 11.2mb .

  3. Now if your on mac use the base64 command line tool to convert the above downloaded image to base64 and check the file size there. You will see the base64 size here is. 5.9mb . base64 -w 0 downloaded_image.jpg > downloaded_image.base64

This is the function i am using in my code to convert an input file image to base64.

async convertToBase64(file) {

  if (file === undefined) {
    throw new Error("File could not be found");
  }

  const fileReader = new FileReader();

  return new Promise((resolve, reject) => {
    fileReader.readAsDataURL(file);

    fileReader.onerror = (error) => {
      reject("Input: File could not be read:" + error);
    };

    fileReader.onloadend = () => {
      resolve(fileReader.result);
    };
  });

}

Why does the filereader.readAsDataURL make the image base64 output extremely large.

How can i make this more efficient?

在此处输入图片说明

I have 5,882,455 bytes for the FileReader vs 5,882,433 bytes for base64 output, if you add the 22 bytes from data:image/png;base64, , we're not too far.

However to the question How can i make this more efficient? , just don't use a data URL here. Whatever you've been told you need it too, it was a lie (I'm 99% percent sure).

Instead you should always prefer to work with the Blob directly.

To display it, use a blob URL:

 inp.onchange = e => { img.src = URL.createObjectURL(inp.files[0]); };
 <input type="file" id="inp"> <img id="img" src="" height="200" alt="Image preview..." accept="image/*">

To send it to your server, send the Blob directly , either through a FormData or, directly from xhr.send() or as the body of a fetch request.

The only case can think of where you would need a data URL version of a binary file on the front end is to generate a standalone document which would need to embed that binary file. For all other use cases I met in my career, Blob where far better suited.


For the message that gets printed in the Chrome's tooltip, that's the size of the USVString that the browser has to hold in memory. It's twice the size of the file you have on disk, because USVStrings are encoded in UTF-16, even though this string holds only ASCII characters.
However, to be sent to your server, or to be saved as a text file, it will generally be reencoded in an 8 bit encoding, and retrieve it's normal size.

So don't take this tooltip as a mean to tell you how big your data is, it's only the size it does take in the browser's allocated memory, but outside, it won't be the same at all.

If you wanna check the size of binary data generated here is a better fiddle, which will convert USVStrings to UTF-8 and keep binary as binary (eg if you pass an ArrayBuffer to it):

 function previewFile() { var preview = document.querySelector('img'); var file = document.querySelector('input[type=file]').files[0]; var reader = new FileReader(); reader.addEventListener("load", function () { console.log(new Blob([reader.result]).size); preview.src = reader.result; }, false); if (file) { reader.readAsDataURL(file); } }
 <!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL --> <input type="file" onchange="previewFile()"><br> <img src="" height="200" alt="Image preview...">

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM