首页 > 解决方案 > FileReader readAsDataURL 创建大型 base64 图像

问题描述

我需要将输入图像(blob)转换为 base64 图像。我知道大小将增加约 1.37。

但是我注意到,firereader.readAsDataUrl与 macOS 上的内置 base64 命令行工具相比,使用图像的大小非常大。

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

重现步骤:

  1. 下载此免费示例图片https://wall.alphacoders.com/big.php?i=685897确保单击“下载”按钮(Downlaod Original 8000x600)。不要使用右键另存为,因为图像会被压缩

  2. 使用 jsfiddle 选择上面下载的图像并检查控制台日志以获取 base 64 的大小。https://jsfiddle.net/b7nkw8j9/你可以看到大小为11.2mb

  3. 现在,如果您在 mac 上使用 base64 命令行工具将上面下载的图像转换为 base64 并检查那里的文件大小。您将在这里看到 base64 大小。5.9mbbase64 -w 0 downloaded_image.jpg > downloaded_image.base64

这是我在代码中用于将输入文件图像转换为 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);
    };
  });

}

为什么filereader.readAsDataURL会使图像base64输出非常大。

我怎样才能使它更有效率?

在此处输入图像描述

标签: javascriptbase64filereader

解决方案


我有 5,882,455 字节用于 FileReader 与 5,882,433 字节用于base64输出,如果您从 中添加 22 字节data:image/png;base64,,我们不会太远。

但是对于这个问题,我怎样才能提高效率?,只是不要在这里使用数据 URL。无论你被告知你也需要它,那都是谎言(我有 99% 的把握)。

相反,您应该始终更喜欢直接使用 Blob。

要显示它,请使用 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/*">

要将其发送到您的服务器,请直接发送 Blob,通过 FormData 或直接从 xhr.send() 或作为获取请求的主体发送。

唯一可以想到在前端需要二进制文件的数据 URL 版本的情况是生成需要嵌入该二进制文件的独立文档。对于我在职业生涯中遇到的所有其他用例,Blob 更适合。


对于在 Chrome 的工具提示中打印的消息,这是浏览器必须在内存中保存的USVString的大小。它是磁盘上文件大小的两倍,因为 USVStrings 是用 UTF-16 编码的,即使这个字符串只包含 ASCII 字符。
但是,要发送到您的服务器或保存为文本文件,通常会以 8 位编码重新编码,并恢复正常大小。

因此,不要将此工具提示作为告诉您数据有多大的手段,它只是浏览器分配的内存中的大小,但在外部,它根本不一样。

如果你想检查这里生成的二进制数据的大小是一个更好的小提琴,它会将 USVStrings 转换为 UTF-8 并将二进制保存为二进制(例如,如果你将 ArrayBuffer 传递给它):

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


推荐阅读