JavaScript >> Javascript 文檔 >  >> Node.js

在 Node.js 中編碼和解碼 Base64 字符串

什麼是 Base64 編碼?

Base64 編碼是一種將數據(通常是二進制)轉換為 ASCII 字符集的方法。重要的是要在這裡提到 Base64 不是一種加密或壓縮技術,儘管它有時會因為它看起來模糊數據的方式而被混淆為加密。事實上,Base64 編碼信息的大小是原始數據實際大小的 1.3333 倍。

Base64是最廣泛使用的base編碼技術,Base16和Base32是另外兩種常用的編碼方案。

Base64 是如何工作的?

將數據轉換為 base64 是一個多步驟的過程。以下是它對文本字符串的工作原理:

  1. 計算輸入文本的 8 位二進製版本
  2. 將 8 位版本的數據重新分組為多個 6 位塊
  3. 查找每個 6 位二進制塊的十進製版本
  4. 通過 Base64 查找表查找每個十進制值的 Base64 符號

為了更好地理解這個概念,我們來看一個例子。

假設我們有字符串“Go win”,我們想將其轉換為 Base64 字符串。第一步是將此字符串轉換為二進制。 “Go win”的二進製版本是:

01000111  01101111  00100000  01110111  01101001  01101110

您可以在此處看到每個字符由 8 位表示。然而,正如我們之前所說,Base64 將 8 位二進制形式的數據轉換為 6 位塊。這是因為 Base64 格式只有 64 個字符:26 個大寫字母、26 個小寫字母、10 個數字字符,以及換行的“+”和“/”符號。

Base64 不使用所有的 ASCII 特殊字符,而只使用這幾個。請注意,Base64 的某些實現使用不同於“+”和“/”的特殊字符。

回到示例,讓我們將 8 位數據分解為 6 位塊。

010001  110110  111100  100000  011101  110110  100101  101110

您並不總是能夠將數據分成完整的 6 位集合,在這種情況下,您將不得不處理填充。

現在對於上面的每個塊,我們必須找到它的十進制值。這些十進制值已在下面給出:

Binary  Decimal
010001  17
110110  54
111100  60
100000  32
011101  29
110110  54
100101  37
101110  46

最後,我們必須查看我們剛剛從二進制數據中計算出的每個十進制的 Base64 值。 Base64編碼表如下:

在這裡可以看到十進制17對應“R”,十進制54對應“2”,以此類推。使用這個編碼表,我們可以看到字符串“Go win”使用 Base64 編碼為“R28gd2lu”。您可以使用任何在線文本到 Base64 轉換器來驗證此結果。

為什麼要使用 Base64 編碼?

以二進制格式發送信息有時會有風險,因為並非所有應用程序或網絡系統都可以處理原始二進製文件。另一方面,ASCII 字符集廣為人知,對大多數係統來說處理起來非常簡單。

例如,電子郵件服務器需要文本數據,因此通常使用 ASCII。因此,如果您想將圖像或任何其他二進製文件發送到電子郵件服務器,您首先需要將其編碼為基於文本的格式,最好是 ASCII。這就是 Base64 編碼在將二進制數據轉換為正確格式時非常方便的地方。

使用 Node.js 編碼 Base64 字符串

在 Node.js 中編碼 Base64 字符串的最簡單方法是通過 Buffer 對象。在 Node.js 中,Buffer 是一個全局對象,這意味著您無需使用 require 語句即可使用 Buffer 應用程序中的對象。

內部 Buffer 是一個不可變的整數數組,也能夠執行許多不同的編碼/解碼。這些包括往返 UTF-8、UCS2、Base64 甚至十六進制編碼。當您編寫處理和操作數據的代碼時,您可能會使用 Buffer 對像在某個時間點。

看看下面的例子。在這裡,我們將使用 Buffer 將文本字符串編碼為 Base64 目的。將以下代碼保存在“encode-text.js”文件中

'use strict';

let data = 'stackabuse.com';
let buff = new Buffer(data);
let base64data = buff.toString('base64');

console.log('"' + data + '" converted to Base64 is "' + base64data + '"');

免費電子書:Git Essentials

查看我們的 Git 學習實踐指南,其中包含最佳實踐、行業認可的標準以及隨附的備忘單。停止谷歌搜索 Git 命令並真正學習 它!

在上面的腳本中,我們創建了一個新的緩衝區對象並將我們想要轉換為 Base64 的字符串傳遞給它。然後我們在剛剛創建的緩衝區對像上調用“toString”方法,並將“base64”作為參數傳遞給它。以“base64”為參數的“toString”方法將以Base64字符串的形式返回數據。運行上面的代碼,你會看到如下輸出。

$ node encode-text.js
"stackabuse.com" converted to Base64 is "c3RhY2thYnVzZS5jb20="

在輸出中,我們可以看到我們轉換為 Base64 的字符串的 Base64 對應項。

使用 Node.js 解碼 Base64 字符串

解碼 Base64 字符串與對其進行編碼非常相似。您必須創建一個新的緩衝區對象並將兩個參數傳遞給它的構造函數。第一個參數是Base64中的數據,第二個參數是“base64”。然後您只需在緩衝區對像上調用“toString”,但這次傳遞給方法的參數將是“ascii”,因為這是您希望 Base64 數據轉換為的數據類型。請查看以下代碼片段以供參考。

'use strict';

let data = 'c3RhY2thYnVzZS5jb20=';
let buff = new Buffer(data, 'base64');
let text = buff.toString('ascii');

console.log('"' + data + '" converted from Base64 to ASCII is "' + text + '"');

將數據添加到“ascii.js”文件並保存。這裡我們使用“Tm8gdG8gUmFjaXNt”作為 Base64 輸入數據。解碼此數據後,應顯示“拒絕種族主義”。這是因為從上一個示例中我們知道“拒絕種族主義”等於“Tm8gdG8gUmFjaXNt”。使用 Node.js 運行上述代碼。它將顯示以下輸出。

將二進制數據編碼為 Base64 字符串

如文章開頭所述,Base64 編碼的主要目的是將二進制數據轉換為文本格式。讓我們看一個將圖像(二進制數據)轉換為 Base64 字符串的示例。看看下面的例子。

'use strict';

const fs = require('fs');

let buff = fs.readFileSync('stack-abuse-logo.png');
let base64data = buff.toString('base64');

console.log('Image converted to base 64 is:\n\n' + base64data);

在上面的代碼中,我們通過 readFileSync() 將圖像加載到緩衝區中 fs的方法 模塊。其餘過程類似於從普通的 ASCII 字符串創建 Base64 字符串。

當你運行上面的代碼時,你會看到如下輸出。

$ node encode-image.js
Image converted to Base64 is:

iVBORw0KGgoAAAANSUhEUgAAABkAAAATCAYAAABlcqYFAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAABWWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpMwidZAAADuUlEQVQ4EbVUTUtcZxR+7ufkXp1SZ4iZRE1EDVQRnTAhowsZMFm40I2rNqUIIev8hvoPQroQXBTqwiAWcd0EglEhiZNajVZrQGXAWAzaZpzMnZn7lXPeeIe5DaWb9Ax33vOec8/znI/3vVI6nfbxP4v8b/iSJIGfzyGfkPi+D13XUalUBL6qqmIvy5+8WuX/r2RCkUzAoIuLi2hqaoLrutjb28P6+josyxJkiqJA07SQXiqVwHaOZYx/itLc3Px9YIxEIlheXsbExATGxsYwMjIiwEdHRwXA/Pw8EokEcrkcDg4OYJomVlZWMDU1JSqfmZlBR0cHbNsOtVoNCHjlTFiSySQMwxAVxONxQbi0tIRMJoPe3l5MT0+jtbUVg4ODYGImY18qlcL4+DhisZjoggCjv1C7uOyenh7Mzs5iY2ND6FQpdnd3sba2JloSjUYxPDyM/v5+TE5OYn9/X9jZtrOzg+3t7WqyAUmoEu419/+HBw9E+eVymbJqAJP39fWBCR3HEU+hUMDQ0JCYGc8um81iYGAAjY2N8DwvwBdraCY8tHhDA1Y3N9Hd3S2yvH37O7RcbsF7AuUsD9+8wdOFBTx/8QJtbW1C5/nMzc3R0D2UyxXk83lRXcAk1V5GCT5sSUGDbeHxy9/EO98M9OOXzT9wfHISxKC1vR0GHfOtrS2g/SouWwU0Xkggu7qO9PUkJFULnbIQyTm6ewu2hF+vnOIIUQwdGlg8f4QF6wvMWBq+pAkaskSnx4FFVUf0CNpcC797KizXQ4oAHhVdXJJ81F7j6kwUynPHlXDPdFB2fRj+KVK0KvT2rbp3uKYryJU11Cke8qqMuOoioeeJ1MPDYxM36m1cNSq4GdFx58RAWvbx8TrXnK4IgR16Em5GK4iqHi5GHHxLgcSDn97WgZPoND+GGZRpPYH85cgiiRQl1ltXxmFFQ5PuopP8TrW5ZyRcWp7AbmkeZefg5+N6PPnbRJdpw/YlfB0vQiPQZwVdZNtFZEVK6D1VTnccJlXzuqTjvOZiq6Rhj2KqLSJsofOHgIl8+t0/qsfDioxmSUWGjrRFzhYi/5Oynrdl3KXHIZDXtF6hil8R6I9FBV/RvDLnXKxSbAdVYhNeINXBMwmXWCTQGG2Y+Jj+dFrfEmiMAtmeowpo9ojTvkD+A/L1UJUMmiVfkuz6WTyZhFRJAgP33j3bsM5k/Fng68UP21hYJyyxZwLWuS2cKMfUSm3rhD0g4E2g197fwMZ+Bgt8rNe2iP2BhL5dgfFzrx8AfECEDdx45a0AAAAASUVORK5CYII=

雖然實際圖像非常小(25x19),但輸出仍然相當大,部分原因是 Base64 增加了數據的大小,正如我們前面提到的。

將 Base64 字符串解碼為二進制數據

這裡的反向過程與我們在前面部分中看到的解碼 Base64 字符串的方式非常相似。最大的區別是輸出目的地和數據是如何寫入那裡的。我們來看例子:

'use strict';

const fs = require('fs');

let data = 'iVBORw0KGgoAAAANSUhEUgAAABkAAAATCAYAAABlcqYFAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAA' + 
'CA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAABWWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0' +
'YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly' +
'93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAg' +
'ICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZm' +
'Y6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpMwidZAAADuUlEQVQ4EbVU' +
'TUtcZxR+7ufkXp1SZ4iZRE1EDVQRnTAhowsZMFm40I2rNqUIIev8hvoPQroQXBTqwiAWcd0EglEhiZNajVZrQGXAWAzaZpzMnZn7lXPeeIe5Da' +
'Wb9Ax33vOec8/znI/3vVI6nfbxP4v8b/iSJIGfzyGfkPi+D13XUalUBL6qqmIvy5+8WuX/r2RCkUzAoIuLi2hqaoLrutjb28P6+josyxJkiqJA' +
'07SQXiqVwHaOZYx/itLc3Px9YIxEIlheXsbExATGxsYwMjIiwEdHRwXA/Pw8EokEcrkcDg4OYJomVlZWMDU1JSqfmZlBR0cHbNsOtVoNCHjlTF' +
'iSySQMwxAVxONxQbi0tIRMJoPe3l5MT0+jtbUVg4ODYGImY18qlcL4+DhisZjoggCjv1C7uOyenh7Mzs5iY2ND6FQpdnd3sba2JloSjUYxPDyM' +
'/v5+TE5OYn9/X9jZtrOzg+3t7WqyAUmoEu419/+HBw9E+eVymbJqAJP39fWBCR3HEU+hUMDQ0JCYGc8um81iYGAAjY2N8DwvwBdraCY8tHhDA1' +
'Y3N9Hd3S2yvH37O7RcbsF7AuUsD9+8wdOFBTx/8QJtbW1C5/nMzc3R0D2UyxXk83lRXcAk1V5GCT5sSUGDbeHxy9/EO98M9OOXzT9wfHISxKC1' +
'vR0GHfOtrS2g/SouWwU0Xkggu7qO9PUkJFULnbIQyTm6ewu2hF+vnOIIUQwdGlg8f4QF6wvMWBq+pAkaskSnx4FFVUf0CNpcC797KizXQ4oAHh' +
'VdXJJ81F7j6kwUynPHlXDPdFB2fRj+KVK0KvT2rbp3uKYryJU11Cke8qqMuOoioeeJ1MPDYxM36m1cNSq4GdFx58RAWvbx8TrXnK4IgR16Em5G' +
'K4iqHi5GHHxLgcSDn97WgZPoND+GGZRpPYH85cgiiRQl1ltXxmFFQ5PuopP8TrW5ZyRcWp7AbmkeZefg5+N6PPnbRJdpw/YlfB0vQiPQZwVdZN' +
'tFZEVK6D1VTnccJlXzuqTjvOZiq6Rhj2KqLSJsofOHgIl8+t0/qsfDioxmSUWGjrRFzhYi/5Oynrdl3KXHIZDXtF6hil8R6I9FBV/RvDLnXKxS' +
'bAdVYhNeINXBMwmXWCTQGG2Y+Jj+dFrfEmiMAtmeowpo9ojTvkD+A/L1UJUMmiVfkuz6WTyZhFRJAgP33j3bsM5k/Fng68UP21hYJyyxZwLWuS' +
'2cKMfUSm3rhD0g4E2g197fwMZ+Bgt8rNe2iP2BhL5dgfFzrx8AfECEDdx45a0AAAAASUVORK5CYII=';

let buff = new Buffer(data, 'base64');
fs.writeFileSync('stack-abuse-logo-out.png', buff);

console.log('Base64 image data converted to file: stack-abuse-logo-out.png');

在這裡您可以看到我們從 Base64 數據開始(也可以從套接字或其他一些通信線路接收)並將其加載到 Buffer 目的。創建緩衝區時,我們告訴它它在 base64 格式,允許緩衝區相應地解析它以供內部存儲。

要將數據保存回原始 PNG 格式,我們只需傳遞 Buffer 反對我們的 fs.writeFileSync 方法,它會為我們進行轉換。

結論

Base64 編碼是將二進制數據轉換為純 ASCII 文本的最常用方法之一。它是一種非常有用的格式,用於在一個或多個無法輕鬆處理二進制數據(例如 HTML 標記中的圖像或 Web 請求)的系統之間進行通信。

在 Node.js 中,Buffer 對象可用於將 Base64 字符串與許多其他格式進行編碼和解碼,讓您可以根據需要輕鬆地來迴轉換數據。

您通常在 Node.js 中使用 Base64 格式做什麼?請在評論中告訴我們!


Tutorial JavaScript 教程
  1. 餘燼時報 - 第 179 期

  2. JavaScript 中的哈希標籤是做什麼用的?

  3. 使用 Elasticdump 的實用指南

  4. 我在代碼審查中學到的一個簡單的東西:標記模板

  5. 為不起眼的 console.log 辯護

  6. 如何在html中的buttonclick上在新窗口中執行javascript函數

  7. 代碼連同 Fetch API

  1. 使用 HTML 和 JavaScript 開發搖滾樂隊遊戲

  2. JavaScript Promise 到底是什麼?

  3. 5分鐘掌握React state和props的藝術

  4. 快速 mvp cli 工具🔫 🔫

  5. Identity Server 登錄頁面在哪里以及如何自定義?

  6. DOM 和事件驅動架構 - 簡介

  7. 構建 JavaScript 和 Tailwind CSS 主題切換器

  1. 如何使用 RxJS 和 React Hooks

  2. 以電報機器人為例,處理 NestJS 應用程序中的 nodejs 錯誤

  3. 我編寫出色 React 組件的秘訣

  4. 為什麼你應該了解虛擬 DOM