自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

了不起的Base64

開(kāi)發(fā) 前端
今天我們來(lái)講講在各種語(yǔ)言中出鏡率都高的離譜的Base64算法。今天,我們就用我們?cè)诔醺咧姓Z(yǔ)文老師教我們的描述一個(gè)事物的三大步驟:1. 是什么,2. 如何工作,3. 為什么它很重要。來(lái)講講Base64算法。

前言

在我們項(xiàng)目開(kāi)發(fā)中,Base64想必大家都不會(huì)很陌生,Base64是將「二進(jìn)制數(shù)據(jù)」轉(zhuǎn)換為文本的一種優(yōu)雅方式,使存儲(chǔ)和傳輸變得容易。但是,作為一個(gè)合格的程序員,我們應(yīng)該有一種打破砂鍋問(wèn)到底的求助欲望。

所以,今天我們來(lái)講講在各種語(yǔ)言中出鏡率都高的離譜的Base64算法。今天,我們就用我們?cè)诔醺咧姓Z(yǔ)文老師教我們的描述一個(gè)事物的三大步驟:1. 是什么,2. 如何工作,3. 為什么它很重要。來(lái)講講Base64算法。

好了,天不早了,干點(diǎn)正事哇。

我們能所學(xué)到的知識(shí)點(diǎn)

  • 前置知識(shí)點(diǎn)
  • 為什么會(huì)出現(xiàn) Base64 編碼
  • 什么是 Base64 編碼?
  • Base64 使用案例
  • Base64 編碼算法
  • 如何進(jìn)行 Base64 編碼和解碼

1. 前置知識(shí)點(diǎn)

「前置知識(shí)點(diǎn)」,只是做一個(gè)概念的介紹,不會(huì)做深度解釋。因?yàn)?,這些概念在下面文章中會(huì)有出現(xiàn),為了讓行文更加的順暢,所以將本該在文內(nèi)的概念解釋放到前面來(lái)?!溉绻蠹覍?duì)這些概念熟悉,可以直接忽略」同時(shí),由于閱讀我文章的群體有很多,所以有些知識(shí)點(diǎn)可能「我視之若珍寶,爾視只如草芥,棄之如敝履」。以下知識(shí)點(diǎn),請(qǐng)「酌情使用」。

RFC

RFC,全稱(chēng)為Request for Comments,是一種用于定義「互聯(lián)網(wǎng)標(biāo)準(zhǔn)和協(xié)議」的文件系列。

RFC最早由互聯(lián)網(wǎng)工程任務(wù)組(IETF)創(chuàng)建,用于記錄和傳播互聯(lián)網(wǎng)協(xié)議、方法和最佳實(shí)踐的提案、規(guī)范和討論。

「每個(gè) RFC 都有一個(gè)唯一的編號(hào)」,通常以RFC開(kāi)頭,后面跟著一個(gè)數(shù)字,例如RFC 791、RFC 2616等。RFC文檔通常包含了協(xié)議規(guī)范、技術(shù)說(shuō)明、最佳實(shí)踐、標(biāo)準(zhǔn)化提案等,以促進(jìn)互聯(lián)網(wǎng)技術(shù)的發(fā)展和互操作性。

我們可以在IETF-datatracker[1]中輸入指定的編號(hào)或者查找的關(guān)鍵字進(jìn)行搜尋。

圖片圖片

以下是一些常見(jiàn)的RFC文檔,大家可以翻閱自己想了解的技術(shù)點(diǎn):

  1. RFC 791 - Internet Protocol (IP): 定義了 IPv4,是互聯(lián)網(wǎng)上最基本的協(xié)議之一。
  2. RFC 793 - Transmission Control Protocol (TCP): 定義了 TCP,一種重要的傳輸協(xié)議,用于可靠的數(shù)據(jù)傳輸。
  3. RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1: 定義了 HTTP 協(xié)議,用于在 Web 上傳輸超文本的基礎(chǔ)通信協(xié)議。
  4. RFC 2326 - Real Time Streaming Protocol (RTSP): RTSP 用于流媒體傳輸,如音頻和視頻流的控制。
  5. RFC 5246 - The Transport Layer Security (TLS) Protocol Version 1.2: 定義了 TLS 1.2,用于安全地傳輸數(shù)據(jù),如 HTTPS 協(xié)議中使用的加密通信。
  6. RFC 4648[2] - 這是咱們今天的主角,Base64的相關(guān)內(nèi)容

Latin-1 字符集

Latin-1,也稱(chēng)為ISO-8859-1,是一種由國(guó)際標(biāo)準(zhǔn)化組織(ISO)認(rèn)可的「8 位字符集」,代表了「西歐語(yǔ)言的字母表」。正如其名稱(chēng)所示,「它是ISO-8859的一個(gè)子集」,該標(biāo)準(zhǔn)還包括用于寫(xiě)作系統(tǒng)如西里爾文、希伯來(lái)文和阿拉伯文的其他相關(guān)字符集。它被大多數(shù)Unix系統(tǒng)以及Windows系統(tǒng)使用。

Latin-1有時(shí)被不太準(zhǔn)確地稱(chēng)為「擴(kuò)展 ASCII」。

這是因?yàn)槠渥址那?128 個(gè)字符與美國(guó) ASCII 標(biāo)準(zhǔn)相同。其余字符集包含了帶重音的字符和符號(hào)。

關(guān)于更詳細(xì)的Latin-1的表格,可以參考Latin-1-table[3]

btoa

btoa 是 JavaScript 中的一個(gè)內(nèi)置函數(shù),用于將二進(jìn)制數(shù)據(jù)(通常是 8 位字節(jié))編碼為 Base64 字符串。它的名稱(chēng)是 binary to ASCII 的縮寫(xiě),用于將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換為文本字符串,以便在文本協(xié)議中傳輸或存儲(chǔ)。

用法:

btoa 函數(shù)接受一個(gè)字符串參數(shù),該字符串包含二進(jìn)制數(shù)據(jù)。它將該二進(jìn)制數(shù)據(jù)轉(zhuǎn)換為 Base64 編碼的字符串。

const binaryData = "front789";
const base64String = btoa(binaryData);
console.log(base64String);

這段代碼將 front789 這個(gè)字符串轉(zhuǎn)換為 Base64 編碼的字符串并將結(jié)果打印到控制臺(tái)。

限制:

盡管 btoa 是一個(gè)有用的函數(shù),但它有一些限制:

  1. 「只能編碼字符串:」 btoa 函數(shù)只接受字符串作為參數(shù),而不接受其他類(lèi)型的數(shù)據(jù)(如二進(jìn)制數(shù)組)。如果需要編碼二進(jìn)制數(shù)據(jù),需要先將其轉(zhuǎn)換為字符串。
  2. 「字符集限制:」 btoa 函數(shù)僅支持 Latin-1 字符集,這意味著它只能編碼包含在 Latin-1 字符集內(nèi)的字符。如果字符串包含超出 Latin-1 字符集的字符,那么會(huì)導(dǎo)致編碼失敗。
  3. 「不適合加密:」Base64 編碼不是加密,它只是一種編碼方式,不提供安全性。如果需要加密數(shù)據(jù),應(yīng)該使用專(zhuān)門(mén)的加密算法而不是僅僅進(jìn)行 Base64 編碼。
  4. 「數(shù)據(jù)大小增加:」 Base64 編碼會(huì)增加數(shù)據(jù)大小。通常情況下,Base64 編碼后的數(shù)據(jù)會(huì)比原始二進(jìn)制數(shù)據(jù)更大,這可能會(huì)對(duì)數(shù)據(jù)傳輸和存儲(chǔ)造成額外開(kāi)銷(xiāo)。

Data URL

Data URL 是一種統(tǒng)一資源標(biāo)識(shí)符(URI)方案,用于將數(shù)據(jù)嵌入到文檔中,而不是從外部文件加載數(shù)據(jù)。Data URL 允許我們將數(shù)據(jù)(如文本、圖像、音頻等)直接包含在網(wǎng)頁(yè)或文檔中,而不需要額外的 HTTP 請(qǐng)求。這種方式對(duì)于小型資源或需要避免外部請(qǐng)求的情況非常有用。

Data URL 的基本結(jié)構(gòu)如下:

data:[<mediatype>][;base64],<data>

其中:

  • <mediatype> 是可選的媒體類(lèi)型(例如,text/plain 或 image/png),用于描述數(shù)據(jù)的類(lèi)型。如果被省略,則默認(rèn)值為 text/plain;charset=US-ASCII。
  • ;base64 是可選的,表示數(shù)據(jù)以 Base64 編碼方式包含。如果省略了 ;base64,則數(shù)據(jù)將以純文本方式包含。
  • <data> 包含實(shí)際的數(shù)據(jù),可以是文本或二進(jìn)制數(shù)據(jù)。

以下是 Data URL 的一些常見(jiàn)用途和示例:

  • 「嵌入圖像:」Data URL 可用于將圖像直接嵌入HTML或CSS中,而不需要外部圖像文件。例如,將一張 PNG 圖像嵌入 HTML 中:
<img
  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/wAABgAB/OGirwAAAABJRU5ErkJggg=="
  alt="Embedded Image"
/>
  • 「內(nèi)聯(lián) CSS:」Data URL可用于內(nèi)聯(lián)CSS樣式表,以減少外部CSS文件的請(qǐng)求。例如,將CSS樣式表嵌入 HTML 中:
<style>
  body {
    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/wAABgAB/OGirwAAAABJRU5ErkJggg==);
  }
</style>
  • 「嵌入字體:」Data URL可用于嵌入自定義字體,以確保字體在不同設(shè)備上顯示一致。例如,嵌入一個(gè)字體文件:
@font-face {
  font-family: "CustomFont";
  src: url(data:application/font-woff;base64,d09GRgABAAAA...) format("woff");
}
  • 「內(nèi)聯(lián)腳本:」Data URL可用于內(nèi)聯(lián)小型JavaScript腳本,以減少外部腳本文件的請(qǐng)求。例如,內(nèi)聯(lián)一個(gè)簡(jiǎn)單的JavaScript函數(shù):
<script>
  let greeting = "前端柒八九";
  alert(greeting);
</script>

2. 為什么會(huì)出現(xiàn) Base64 編碼

要理解為什么需要 Base64 編碼,我們需要了解一些計(jì)算機(jī)歷史。

計(jì)算機(jī)以二進(jìn)制(0 和 1)進(jìn)行通信,但人們通常希望使用更豐富的數(shù)據(jù)形式進(jìn)行通信,如文本或圖像?!笧榱嗽谟?jì)算機(jī)之間傳輸數(shù)據(jù),首先必須將其編碼為 0 和 1,然后再解碼」。以文本為例,有許多不同的編碼方式。如果我們都能就一個(gè)單一的編碼方式達(dá)成一致,那將會(huì)簡(jiǎn)單得多,但很遺憾,這并不是事實(shí)。針對(duì)這塊的內(nèi)容,可以參考了不起的 Unicode

最初創(chuàng)建了許多不同的編碼方式(例如 Baudot 編碼),每種方式「使用不同數(shù)量的比特來(lái)表示一個(gè)字符」,直到最終 ASCII 成為一個(gè)標(biāo)準(zhǔn),「每個(gè)字符使用 7 位」。然而,大多數(shù)「計(jì)算機(jī)將二進(jìn)制數(shù)據(jù)存儲(chǔ)為每個(gè)字節(jié)由 8 位組成的數(shù)據(jù)」,因此 ASCII 不適合傳輸這種類(lèi)型的數(shù)據(jù)。一些系統(tǒng)甚至?xí)h除最高位。

為解決這些問(wèn)題,引入了 Base64 編碼。這允許我們「將任意字節(jié)編碼為已知不會(huì)損壞的字節(jié)」(ASCII 字母數(shù)字字符和一些符號(hào))。缺點(diǎn)是使用 Base64 對(duì)消息進(jìn)行編碼會(huì)增加其長(zhǎng)度 - 「每 3 個(gè)字節(jié)的數(shù)據(jù)編碼為 4 個(gè) ASCII 字符」。

要可靠地發(fā)送文本,我們可以首先使用自己選擇的文本編碼(例如 UTF-8)將其編碼為字節(jié),然后將結(jié)果的二進(jìn)制數(shù)據(jù)使用 Base64 編碼為可安全傳輸?shù)?nbsp;ASCII 文本字符串。接收者反轉(zhuǎn)此過(guò)程以恢復(fù)原始消息。當(dāng)然,這需要接收者知道使用了哪種編碼,通常需要單獨(dú)發(fā)送這些信息。

我們來(lái)看一個(gè)示例:

我希望發(fā)送一個(gè)帶有兩行的文本消息:

Hello
world!

如果我將其發(fā)送為 ASCII(或 UTF-8),它將如下所示:

72 101 108 108 111 10 119 111 114 108 100 33

某些系統(tǒng)會(huì)破壞字節(jié) 10,所以我們可以將這些字節(jié)作為 Base64 字符串進(jìn)行 Base64 編碼:

SGVsbG8Kd29ybGQh

這里的所有字節(jié)都是已知的安全字節(jié),所以很少有機(jī)會(huì)使任何系統(tǒng)損壞此消息。我可以發(fā)送這個(gè)消息而不是我的原始消息,然后讓接收者反轉(zhuǎn)此過(guò)程以恢復(fù)原始消息。

3. 什么是 Base64 編碼?

Base64編碼將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換為文本,具體來(lái)說(shuō)是ASCII文本。生成的文本僅包含A-Z、a-z、0-9以及符號(hào)+和/這些字符。

而在之前我們?cè)诹瞬黄鸬?Unicode中介紹過(guò)ASCII的。

由于字母表中有 26 個(gè)字母,我們有26 + 26 + 10 + 2(64)個(gè)字符。因此,這種編碼被命名為Base64。這 64 個(gè)字符被認(rèn)為是「安全」的,也就是說(shuō),與字符<、>、\n等不同,「它們不會(huì)被舊計(jì)算機(jī)和程序誤解」。

下面是經(jīng)過(guò) Base64 編碼的文本front789的樣子:ZnJvbnQ3ODk=。

還有一點(diǎn)需要注意,如果在使用JS對(duì)某一個(gè)文本進(jìn)行準(zhǔn)換時(shí),如果該文本包含非Latin1字符的字符串,會(huì)報(bào)錯(cuò),所以我們需要對(duì)其進(jìn)行準(zhǔn)換處理。

// 原始文本字符串,包含非Latin1字符
const text = "前端柒八九";

// 創(chuàng)建一個(gè) TextEncoder 對(duì)象,用于將文本編碼為字節(jié)數(shù)組
const encoder = new TextEncoder();

// 使用 TextEncoder 對(duì)象將文本編碼為字節(jié)數(shù)組
const data = encoder.encode(text);

// 使用 String.fromCharCode 和展開(kāi)運(yùn)算符 (...) 將字節(jié)數(shù)組轉(zhuǎn)換為字符串
// 然后使用 btoa 函數(shù)將字符串轉(zhuǎn)換為 Base64 編碼
const base64 = btoa(String.fromCharCode(...data));

// 打印 Base64 編碼后的結(jié)果
console.log(base64); //5YmN56uv5p+S5YWr5Lmd

我們?cè)谶@里并沒(méi)有加密文本。給定Base64編碼的數(shù)據(jù),非常容易將其轉(zhuǎn)換回(解碼)原始文本。我們「只是改變了數(shù)據(jù)的表示」,即編碼。

在本質(zhì)上,Base64編碼使用一組特定的、減少的字符來(lái)「編碼二進(jìn)制數(shù)據(jù)」,以防止數(shù)據(jù)損壞。

Base64字母表Base64字母表

由于只有64個(gè)字符可用于編碼,我們可以?xún)H使用6位來(lái)表示它們,因?yàn)?^6 = 64。每個(gè)Base64數(shù)字表示6位數(shù)據(jù)。一個(gè)字節(jié)中有8位,而 8 和 6 的「最小公倍數(shù)」是 24。因此,「24 位,或 3 個(gè)字節(jié),可以用四個(gè) 6 位的 Base64 數(shù)字表示」。

4. Base64 使用案例

我們可能在HTML文檔中使用了<img src="789.jpeg">標(biāo)簽來(lái)包含圖像。其實(shí),我們可以直接將「圖像數(shù)據(jù)」嵌入到 HTML 中,而不必使用外鏈!數(shù)據(jù)URL可以做到這一點(diǎn),它們使用Base64編碼的文本來(lái)內(nèi)聯(lián)嵌入文件。

<img src="data:image/gif;base64,xxxxbase64encodedtextxxxx" />

data:[<mime type
  >][;charset=<charset>][;base64],<encoded data></encoded></charset
></mime>

另一個(gè)常見(jiàn)的用例是當(dāng)我們需要在網(wǎng)絡(luò)上傳輸或存儲(chǔ)一些二進(jìn)制數(shù)據(jù),而網(wǎng)絡(luò)只能處理文本或ASCII數(shù)據(jù)時(shí)。這確保了數(shù)據(jù)在傳輸過(guò)程中保持不變。還有就是在 URL 中傳遞數(shù)據(jù)時(shí),當(dāng)數(shù)據(jù)包含不適合 URL 的字符時(shí),此時(shí)Base64就有了用武之地。

Base編碼還在許多應(yīng)用程序中使用,因?yàn)樗沟每梢允褂梦谋揪庉嬈鱽?lái)操作對(duì)象。

我們還可以使用 Base64 編碼「將文件作為文本傳輸」。

  • 首先,獲取文件的字節(jié)并將它們「編碼為 Base64」。
  • 然后傳輸 Base64 編碼的字符串,然后在接收端「解碼為原始文件內(nèi)容」。

5. Base64 編碼算法

以下是將一些文本轉(zhuǎn)換為 Base64 的簡(jiǎn)單算法。

  1. 將文本轉(zhuǎn)換為其二進(jìn)制表示。
  2. 將比特位分組為每組6位。
  3. 將每個(gè)組轉(zhuǎn)換為0到63的十進(jìn)制數(shù)。它不能大于 64,因?yàn)槊拷M只有 6 位。
  • 如果轉(zhuǎn)換為十進(jìn)制數(shù)的數(shù)字大于 64,我們可以將其取模64 例如:151 % 64 = 23
  1. 使用Base64字母表將此十進(jìn)制數(shù)轉(zhuǎn)換為等效的Base64字符。

通過(guò)上述操作我們會(huì)得到一個(gè)Base64編碼的字符串。如果最后一組中的比特位不足,可以使用=或==作為填充。

讓我們以front7作為范例,來(lái)模擬上述操作。

  • 通過(guò)首先將每個(gè)字符轉(zhuǎn)換為其對(duì)應(yīng)的ASCII數(shù)字,然后將該十進(jìn)制數(shù)轉(zhuǎn)換為二進(jìn)制,(使用ASCII 轉(zhuǎn)二進(jìn)制工具[4])將文本front7轉(zhuǎn)換為二進(jìn)制:
01100110 01110010 01101111 01101110 01110100 00110111

f        r        o        n        t        7
  • 將比特位分組為每組6位:
011001 100111 001001 101111 011011 100111 010000 110111
  • 將每個(gè)組轉(zhuǎn)換為 0 到 63 之間的十進(jìn)制數(shù):
011001 100111 001001 101111 011011 100111 010000 110111

25     23     9     47     27     23      16       27
  • 這步中如果數(shù)據(jù)超過(guò) 64,需要對(duì)其 64 取模
  1. 現(xiàn)在使用Base64字母表將每個(gè)十進(jìn)制數(shù)轉(zhuǎn)換為其Base64表示:
25  23   9   47  27  23  16  27

Z    n   J   v   b   n   Q   3

然后我們完成了。名字front7在 Base64 中表示為ZnJvbnQ3。

乍一看,Base64 編碼的好處并不是很明顯。

想象一下,如果我們有一張圖片或一個(gè)「敏感文件」(PDF、文本、視頻等),而不是簡(jiǎn)單的字符串,我們想將它存儲(chǔ)為文本。我們可以首先將其轉(zhuǎn)換為二進(jìn)制,然后進(jìn)行 Base64 編碼,以獲得相應(yīng)的 ASCII 文本。

現(xiàn)在我們可以將該文本發(fā)送或存儲(chǔ)在任何地方,以任何我們喜歡的方式,而不必?fù)?dān)心一些舊設(shè)備、協(xié)議或軟件會(huì)錯(cuò)誤解釋原始二進(jìn)制數(shù)據(jù)以損壞我們的文件。

6. 如何進(jìn)行 Base64 編碼和解碼

所有編程語(yǔ)言都支持將數(shù)據(jù)編碼為 Base64 格式以及從 Base64 格式解碼數(shù)據(jù)。

JS 中處理

// 簡(jiǎn)單字符串
const text1 = "front789";
bota(text1); // ZnJvbnQ3ODk=

// 超出`Latin-1`字符的字符串
const text2 = "前端柒八九";
const encoder = new TextEncoder();
const data = encoder.encode(text);
const base64 = btoa(String.fromCharCode(...data));
console.log(base64); //5YmN56uv5p+S5YWr5Lmd

Rust 中處理

用Rust的話,我們可以直接用 base64 crate。

在 Cargo.toml 文件中添加以下內(nèi)容:

[dependencies]
base64 = "0.21.5"
use base64::{Engine as _, engine::general_purpose};

let orig = b"data";
let encoded: String = general_purpose::STANDARD_NO_PAD.encode(orig);
assert_eq!("ZGF0YQ", encoded);
assert_eq!(orig.as_slice(), &general_purpose::STANDARD_NO_PAD.decode(encoded).unwrap());

// or, URL-safe
let encoded_url = general_purpose::URL_SAFE_NO_PAD.encode(orig);

想了解更多關(guān)于Rust如何處理Base64,可以查看Rust base64[5]

此外,終端也內(nèi)置支持 Base64 編碼。在終端中嘗試以下命令:

echo "前端柒八九" | base64
5YmN56uv5p+S5YWr5LmdCg==

$ echo "5YmN56uv5p+S5YWr5LmdCg==" | base64 -d
前端柒八九


責(zé)任編輯:武曉燕 來(lái)源: 前端柒八九
相關(guān)推薦

2016-12-13 13:50:06

JAVA轉(zhuǎn)換Base64

2021-02-05 05:26:33

字節(jié)ASCII控制

2014-02-20 10:28:28

JavaScriptBase64

2025-02-11 00:00:10

Base64編碼二進(jìn)制

2021-09-07 08:59:09

編碼Base64解碼

2010-03-03 16:14:05

Python base

2024-07-31 10:22:49

Go語(yǔ)言編碼

2021-03-05 09:10:19

base64編碼

2021-08-26 05:27:08

Base64 字節(jié)流算法

2025-04-23 00:04:00

2024-02-28 23:07:42

GolangBase64編碼

2022-10-29 19:58:09

Base64Bashshell

2025-01-14 12:18:06

Base64加解密字符

2022-06-06 08:31:05

Base64編碼Base58

2024-07-11 08:42:57

2019-08-09 11:40:38

JavaScriptCSS技術(shù)

2019-07-23 08:55:46

Base64編碼底層

2023-03-01 11:02:12

2016-10-13 13:12:43

微信小程序javascript

2022-09-28 08:01:33

JavaScript二進(jìn)制
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)