[英]Convert binary data to base64 does not work with btoa unescape
I am new to React and want to display an image downloaded as binary data.我是 React 的新手,想显示下载为二进制数据的图像。 I download the image data from api call to adobe lightroom api. The api call works since the image is displayed in Postman without problems.
我从 api 调用 adobe lightroom api 下载图像数据。api 调用有效,因为图像在 Postman 中显示没有问题。 I can also save the image data to a jpeg-file and it is displayed ok.
我还可以将图像数据保存到 jpeg 文件中,并且可以正常显示。
In React I want to do <img src={`data:image/jpeg;base64,${theImage}`} />
and for that to work I need to convert the binary data to a base64 encoded string.在 React 中,我想做
<img src={`data:image/jpeg;base64,${theImage}`} />
为了让它工作,我需要将二进制数据转换为 base64 编码的字符串。 When i convert the downloaded jpeg using cat image.jpeg|base64 > base64.txt
the resulting string works in my React app.当我使用
cat image.jpeg|base64 > base64.txt
转换下载的 jpeg 时,生成的字符串在我的 React 应用程序中有效。
But when I try var theImage = btoa(binarydata)
in React I get Unhandled Rejection (InvalidCharacterError): Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.
但是当我在 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.
After searching the issue I try use var theImage = btoa(unescape(encodeURIComponent( binarydata )))
and similar proposed solution but resulting strings from those does not turn out to be a valid base64 encodings of the jpeg as it seem (I try the result from the conversions in online base64->image services and no image is shown).搜索问题后,我尝试使用
var theImage = btoa(unescape(encodeURIComponent( binarydata )))
和类似的建议解决方案,但从中得到的字符串并不是 jpeg 的有效 base64 编码,因为它看起来(我尝试了结果来自在线 base64-> 图像服务中的转换,没有显示图像)。 I have also tried other proposed solution such as base64-js and js-base64 libraries and non of those create a valid base64 valid image that can be shown in my React code.我还尝试了其他建议的解决方案,例如base64-js和js-base64库,但没有一个创建有效的 base64 有效图像,可以在我的 React 代码中显示。
How do you convert jpeg binary data to valid Base64 image encoding when btoa
throws latin1 exception?当
btoa
抛出 latin1 异常时,如何将 jpeg 二进制数据转换为有效的 Base64 图像编码?
You've said you're using axios.get
to get the image from the server.你说过你正在使用
axios.get
从服务器获取图像。 What you'll presumably get back will be a Buffer
or ArrayBuffer
or Blob
, etc., but it depends on what you do with the response you get from axios
.您可能会返回
Buffer
或ArrayBuffer
或Blob
等,但这取决于您如何处理从axios
获得的响应。
I don't use axios
(never felt the need to), but you can readily get a data
URI for binary data from the server via fetch
:我不使用
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);
Or more concisely:或者更简洁:
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);
Here's how that works:这是它的工作原理:
fetch
only rejects its promise on network errors, not HTTP errors; those are reported via the status
and ok
props.fetch
仅拒绝其 promise网络错误,而不是 HTTP 错误;这些通过status
和ok
道具报告。ArrayBuffer
;ArrayBuffer
; the buffer will have the binary image data.Uint8Array
(using that buffer) to access them.Uint8Array
(使用该缓冲区)来访问它们。Array.from
and in its mapping function (called for each byte), we'll use String.fromCharCode
to convert the byte to a character.Array.from
和它的映射 function(为每个字节调用)来做到这一点,我们将使用String.fromCharCode
将字节转换为字符。 (It's not really much of a conversion. The byte 25 [for instance] becomes the character with character code 25 in the string.) Looking at the docs, it looks like axios
lets you provide the option responseType: "arraybuffer"
to get an array buffer.查看文档,看起来
axios
让您提供选项responseType: "arraybuffer"
来获取数组缓冲区。 If I'm reading right, you could use axios
like this:如果我没看错,你可以像这样使用
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);
Fetch your image as a Blob and generate a blob:// URI from it.将图像作为Blob获取并从中生成blob:// URI 。
data:// URLs are completely inefficient and require far more memory space than blob:// URLs. data:// URLs是完全低效的,需要比 blob:// URLs 多得多的 memory 空间。 The data:// URL takes 34% more space than the actual data it represents and it must be stored in the DOM + decoded as binary again to be read by the image decoder.
data:// URL比它代表的实际数据多占用 34% 的空间,它必须存储在 DOM 中 + 再次解码为二进制文件才能被图像解码器读取。 The blob:// URI on the other hand is just a pointer to the binary data in memory.
另一方面, blob:// URI只是指向 memory 中二进制数据的指针。
blob:// URLs are not perfect, but until browsers implement srcDoc
correctly, it's still the best we have. blob:// URL并不完美,但在浏览器正确实现
srcDoc
之前,它仍然是我们拥有的最好的。
So if as per the comments you are using axios in a browser, you can do因此,如果根据您在浏览器中使用 axios 的评论,您可以这样做
const blob = await axios.get("/path/to/resource", {responseType: "blob"});
const theImage = URL.createObjectURL(blob);
And if you want to use the fetch API如果你想使用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);
Ps:附:
If you don't have any particular reason to fetch this image through AJAX (eg credentials or special POST params), then pass directly the URL of the resource as the src
of your image:如果您没有任何特殊原因通过 AJAX 获取此图像(例如凭据或特殊的 POST 参数),则直接将资源的 URL 作为图像的
src
传递:
<img src="/path/to/resource" />
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.