簡體   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