繁体   English   中英

将二进制数据转换为 base64 不适用于 btoa unescape

[英]Convert binary data to base64 does not work with btoa unescape

我是 React 的新手,想显示下载为二进制数据的图像。 我从 api 调用 adobe lightroom api 下载图像数据。api 调用有效,因为图像在 Postman 中显示没有问题。 我还可以将图像数据保存到 jpeg 文件中,并且可以正常显示。

在 React 中,我想做<img src={`data:image/jpeg;base64,${theImage}`} />为了让它工作,我需要将二进制数据转换为 base64 编码的字符串。 当我使用cat image.jpeg|base64 > base64.txt转换下载的 jpeg 时,生成的字符串在我的 React 应用程序中有效。

但是当我在 React 中尝试var theImage = btoa(binarydata)时,我得到Unhandled Rejection (InvalidCharacterError): Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.

搜索问题后,我尝试使用var theImage = btoa(unescape(encodeURIComponent( binarydata )))和类似的建议解决方案,但从中得到的字符串并不是 jpeg 的有效 base64 编码,因为它看起来(我尝试了结果来自在线 base64-> 图像服务中的转换,没有显示图像)。 我还尝试了其他建议的解决方案,例如base64-jsjs-base64库,但没有一个创建有效的 base64 有效图像,可以在我的 React 代码中显示。

btoa抛出 latin1 异常时,如何将 jpeg 二进制数据转换为有效的 Base64 图像编码?

你说过你正在使用axios.get从服务器获取图像。 您可能会返回BufferArrayBufferBlob等,但这取决于您如何处理从axios获得的响应。

我不使用axios (从未觉得有必要),但您可以通过fetch从服务器轻松获取二进制数据的data URI:

// 1.
const response = await fetch("/path/to/resource");
// 2.
if (!response.ok) {
    throw new Error("HTTP error " + response.status);
}
// 3.
const buffer = await response.arrayBuffer();
// 4.
const byteArray = new Uint8Array(buffer);
// 5.
const charArray = Array.from(byteArray, byte => String.fromCharCode(byte));
// 6.
const binaryString = charArray.join("");
// 7.
const theImage = btoa(binaryString);

或者更简洁:

const response = await fetch("/path/to/resource");
if (!response.ok) {
    throw new Error("HTTP error " + response.status);
}
const buffer = await response.arrayBuffer();
const binaryString = Array.from(new Uint8Array(buffer), byte => String.fromCharCode(byte)).join("");
const theImage = btoa(binaryString);

这是它的工作原理:

  1. 我们请求图像数据。
  2. 我们检查请求是否有效( fetch仅拒绝其 promise网络错误,而不是 HTTP 错误;这些通过statusok道具报告。
  3. 我们将响应的主体读入ArrayBuffer 缓冲区将包含二进制图像数据。
  4. 我们想将该缓冲区数据转换为二进制字符串 为此,我们需要单独访问字节,因此我们创建了一个Uint8Array (使用该缓冲区)来访问它们。
  5. 要将该字节数组转换为二进制字符串,我们需要将每个字节转换为其等效字符,并将它们连接在一起形成一个字符串。 让我们通过使用Array.from和它的映射 function(为每个字节调用)来做到这一点,我们将使用String.fromCharCode将字节转换为字符。 (这并不是真正的转换。字节 25 [例如] 变成字符串中字符代码为 25 的字符。)
  6. 现在我们通过将数组中的字符连接成一个字符串来创建二进制字符串。
  7. 最后,我们将该字符串转换为 Base64。

查看文档,看起来axios让您提供选项responseType: "arraybuffer"来获取数组缓冲区。 如果我没看错,你可以像这样使用axios

const response = await axios.get("/path/to/resource", {responseType: "arraybuffer"});
const binaryString = Array.from(new Uint8Array(response.body), v => String.fromCharCode(v)).join("");
const theImage = btoa(binaryString);

将图像作为Blob获取并从中生成blob:// URI

data:// URLs是完全低效的,需要比 blob:// URLs 多得多的 memory 空间。 data:// URL比它代表的实际数据多占用 34% 的空间,它必须存储在 DOM 中 + 再次解码为二进制文件才能被图像解码器读取。 另一方面, blob:// URI只是指向 memory 中二进制数据的指针。

blob:// URL并不完美,但在浏览器正确实现srcDoc之前,它仍然是我们拥有的最好的。

因此,如果根据您在浏览器中使用 axios 的评论,您可以这样做

const blob = await axios.get("/path/to/resource", {responseType: "blob"});
const theImage = URL.createObjectURL(blob);

如果你想使用fetch API

const response = await fetch("/path/to/resource");
if (!response.ok) {
    throw new Error("HTTP error " + response.status);
}
const blob = await response.blob();
const theImage = URL.createObjectURL(blob);

附:
如果您没有任何特殊原因通过 AJAX 获取此图像(例如凭据或特殊的 POST 参数),则直接将资源的 URL 作为图像的src传递:

<img src="/path/to/resource" />

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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