最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

為什么文件上傳要轉(zhuǎn)成Base64?

2023-08-17 20:44 作者:我要吃那朵棉花糖  | 我要投稿

1 前言

最近在開(kāi)發(fā)中遇到文件上傳采用Base64的方式上傳,記得以前剛開(kāi)始學(xué)http上傳文件的時(shí)候,都是通過(guò)content-type為multipart/form-data方式直接上傳二進(jìn)制文件,我們知道都通過(guò)網(wǎng)絡(luò)傳輸最終只能傳輸二進(jìn)制流,所以毫無(wú)疑問(wèn)他們本質(zhì)上都是一樣的,那么為什么還要先轉(zhuǎn)成Base64呢?這兩種方式有什么區(qū)別?帶著這樣的疑問(wèn)我們一起來(lái)分析下。

2 multipart/form-data上傳

先來(lái)看看multipart/form-data的方式,我在本地通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)查看http multipart/form-data方式的文件上傳,html代碼如下

html復(fù)制代碼<!DOCTYPE html> <html> <head> ?? ?<title>上傳文件示例</title> ?? ?<meta charset="UTF-8"> <body> <h1>上傳文件示例</h1> <form action="/upload" method="POST" enctype="multipart/form-data"> ?? ?<label for="file">選擇文件:</label> ?? ?<input type="file" id="file" name="file"><br> ?? ?<label for="tx">說(shuō)明:</label> ?? ?<input type="text" id="tx" name="remark"><br><br> ?? ?<input type="submit" value="上傳"> </form> </body> </html>

頁(yè)面展示也比較簡(jiǎn)單

選擇文件點(diǎn)擊上傳后,通過(guò)edge瀏覽器f12進(jìn)入調(diào)試模式查看到的請(qǐng)求信息。
請(qǐng)求頭如下

在請(qǐng)求頭里Content-Type 為 multipart/form-data; boundary=----WebKitFormBoundary4TaNXEII3UbH8VKo,剛開(kāi)始看肯定有點(diǎn)懵,不過(guò)其實(shí)也不復(fù)雜,可以簡(jiǎn)單理解為在請(qǐng)求體里要傳遞的參數(shù)被分為多部份,每一部分通過(guò)分解符boundary分割,就比如在這個(gè)例子,表單里有file和remark兩個(gè)字段,則在請(qǐng)求體里就被分為兩部分,每一部分通過(guò)boundary=----WebKitFormBoundary4TaNXEII3UbH8VKo來(lái)分隔(實(shí)際上還要加上CRLF回車換行符,回車表示將光標(biāo)移動(dòng)到當(dāng)前行的開(kāi)頭,換行表示一行文本的結(jié)束,也就是新文本行的開(kāi)始)。需要注意下當(dāng)最后一部分結(jié)尾時(shí)需要加多兩個(gè)"-"結(jié)尾。
我們繼續(xù)來(lái)看請(qǐng)求體

第一部分是file字段部分,它的Content-Type為image/png,第二部分為remark字段部分,它沒(méi)有聲明Content-Type,則默認(rèn)為text/plain純文本類型,也就是在例子中輸入的“測(cè)試”,到這里大家肯定會(huì)有個(gè)疑問(wèn),上傳的圖片是放在哪里的,這里怎么沒(méi)看到呢?別急,我猜測(cè)是瀏覽器做了特殊處理,請(qǐng)求體里不顯示二進(jìn)制流,我們通過(guò)Filder抓包工具來(lái)驗(yàn)證下。

可以看到在第一部分有一串亂碼顯示,這是因?yàn)閳D片是二進(jìn)制文件,顯示成文本格式自然就亂碼了,這也證實(shí)了二進(jìn)制文件也是放在請(qǐng)求體里。后端使用框架springboot通過(guò)MultipartFile接受文件也是解析請(qǐng)求體的每一部分最終拿到二進(jìn)制流。

java復(fù)制代碼@RestController public class FileController { ?? ?// @RequestParam可接收Content-Type 類型為:multipart/form-data? ?? ?// 或 application/x-www-form-urlencoded 請(qǐng)求體的內(nèi)容 ?? ?@PostMapping("/upload") ?? ?public String upload(@RequestParam("file") MultipartFile file) { ?? ? ? ?return "test"; ?? ?} }

到此multipart/form-data方式上傳文件就分析完了,關(guān)于multipart/form-data官方說(shuō)明可參考 RFC 7578 - Returning Values from Forms: multipart/form-data (ietf.org)

3 Base64上傳

在http的請(qǐng)求方式中,文件上傳只能通過(guò)multipart/form-data的方式上傳,這樣一來(lái)就會(huì)有比較大的限制,那有沒(méi)其他方式可以突破這一限制,也就是說(shuō)我可以通過(guò)其他的請(qǐng)求方式上傳,比如application/json?當(dāng)然有,把文件當(dāng)成一個(gè)字符串,和其他普通參數(shù)沒(méi)什么兩樣,我們可以通過(guò)其他任意請(qǐng)求方式上傳。如果轉(zhuǎn)成了字符串,那上傳文件就比較簡(jiǎn)單了,但問(wèn)題是我們?cè)趺窗讯M(jìn)制流轉(zhuǎn)成字符串,因?yàn)檫@里面可能會(huì)有很多“坑”,業(yè)界一般的做法是通過(guò)Base64編碼把二進(jìn)制流轉(zhuǎn)成字符串,那為什么不直接轉(zhuǎn)成字符串而要先通過(guò)Base64來(lái)轉(zhuǎn)呢?我們下面來(lái)分析下。

3.1 Base64編碼原理

在分析原理之前,我們先來(lái)回答什么是Base64編碼?首先我們要知道Base64只是一種編碼方式,并不是加解密算法,因此Base64可以編碼,那也可以解碼,它只是按照某種編碼規(guī)則把一些不可顯示字符轉(zhuǎn)成可顯示字符。這種規(guī)則的原理是把要編碼字符的二進(jìn)制數(shù)每6位分為一組,每一組二進(jìn)制數(shù)可對(duì)應(yīng)Base64編碼的可打印字符,因?yàn)橐粋€(gè)字符要用一個(gè)字節(jié)顯示,那么每一組6位Base64編碼都要在前面補(bǔ)充兩個(gè)0,因此總長(zhǎng)度比編碼前多了(2/6) = 1/3,因?yàn)?和8最小公倍數(shù)是24,所以要編碼成Base64對(duì)字節(jié)數(shù)的要求是3的倍數(shù)(24/8=3字節(jié)),對(duì)于不足字節(jié)的需要在后面補(bǔ)充字節(jié)數(shù),補(bǔ)充多少個(gè)字節(jié)就用多少個(gè)"="表示(一個(gè)或兩個(gè)),這么說(shuō)有點(diǎn)抽象,我們通過(guò)下面的例子來(lái)說(shuō)明。
我們對(duì)ASCII碼字符串"AB\nC"(\n和LF都代表?yè)Q行)進(jìn)行Base64編碼,因?yàn)橐还?字節(jié),為了滿足是3的倍數(shù)需要擴(kuò)展到6個(gè)字節(jié),后面補(bǔ)充了2個(gè)字節(jié)。

表3.1

轉(zhuǎn)成二級(jí)制后每6位一組對(duì)應(yīng)不同顏色,每6位前面補(bǔ)充兩個(gè)0組成一個(gè)字節(jié),最終Base64編碼字符是QUIKQw==,Base64編碼表大家可以自行網(wǎng)上搜索查看。

我們通過(guò)運(yùn)行程序來(lái)驗(yàn)證下

最終得出的結(jié)果與我們上面推理的一樣。

3.2 Base64編碼的作用

在聊完原理之后,我們繼續(xù)來(lái)探討文件上傳為什么要先通過(guò)Base64編碼轉(zhuǎn)成字符串而不直接轉(zhuǎn)成字符串?一些系統(tǒng)對(duì)特殊的字符可能存在限制或者說(shuō)會(huì)被當(dāng)做特殊含義來(lái)處理,直接轉(zhuǎn)成普通字符串可能會(huì)失真,因此上傳文件要先轉(zhuǎn)成Base64編碼字符,不能把二進(jìn)制流直接字符串。

另外,相比較multipart/form-data Base64編碼文件上傳比較靈活,它不受請(qǐng)求類型的限制,可以是任何請(qǐng)求類型,因?yàn)樽罱K就是一串字符串,相當(dāng)于請(qǐng)求的一個(gè)參數(shù)字段,它不像二進(jìn)制流只能限定multipart/form-data的請(qǐng)求方式,日常開(kāi)發(fā)中,我們用的比較多的是通過(guò)apllication/json的格式把文件字段放到請(qǐng)求體,這種方式提供了比較便利的可操作性。

4 總結(jié)

本文最后再來(lái)總結(jié)對(duì)比下這兩種文件上傳的方式優(yōu)缺點(diǎn)。
(1)multipart/form-data可以傳輸二進(jìn)制流,效率較高,Base64需要編碼解碼,會(huì)耗費(fèi)一定的性能,效率較低。
(2)Base64不受請(qǐng)求方式的限制,靈活度高,http文件二進(jìn)制流方式傳輸只能通過(guò)multipart/form-data的方式,靈活度低。
因?yàn)殡S著機(jī)器性能的提升,小文件通過(guò)二進(jìn)制流傳輸和字符串傳輸,我們對(duì)這兩種方式時(shí)間延遲的感知差異并不那么明顯,因此大部分情況下我們更多考慮的是靈活性,所以采用Base64編碼的情況也就比較多。

為什么文件上傳要轉(zhuǎn)成Base64?的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
宜君县| 壤塘县| 毕节市| 平潭县| 岗巴县| 阿瓦提县| 常州市| 宁明县| 临沭县| 横峰县| 新晃| 湖南省| 永靖县| 响水县| 尼勒克县| 昂仁县| 石屏县| 黄骅市| 雷州市| 年辖:市辖区| 高陵县| 富阳市| 济南市| 和硕县| 灵丘县| 木兰县| 蒙阴县| 贺州市| 古田县| 永靖县| 本溪市| 牙克石市| 喜德县| 新安县| 金湖县| 利川市| 云阳县| 墨竹工卡县| 临颍县| 奇台县| 兴海县|