摘要:再深入想一想,如果不使用這些庫(kù),怎么上傳文件可能會(huì)難倒很多人,所以這篇文章簡(jiǎn)單講講文件上傳的原理,其實(shí)就是根據(jù)協(xié)議的定義,封裝一個(gè)消息體。
今年第三季度工作上完成了一個(gè)比較有意思的項(xiàng)目,類(lèi)似于外包的性質(zhì),主要任務(wù)就是提供一大堆API,其中一個(gè)API是上傳附件,完成開(kāi)發(fā)后,對(duì)方的程序員問(wèn)我,這個(gè)API怎么調(diào)用,當(dāng)時(shí)我就愣住了,因?yàn)樽约阂矝](méi)想過(guò)這個(gè)問(wèn)題,一般情況下,我就是用 Curl 命令行或 Postman 測(cè)試API的。
針對(duì)文件上傳,我使用 Curl 測(cè)試,比如:
# 使用@引用一個(gè)文件
$ curl -F"param=value" -F"file=@/path/file.png" http://localhost/api.php
如果使用Postman測(cè)試,如下圖:
注意觀察form-data和File標(biāo)簽。
看上去是不是很簡(jiǎn)單,現(xiàn)在換個(gè)角度,你想以代碼的方式上傳文件API,怎么辦?也非常簡(jiǎn)單,很多開(kāi)發(fā)語(yǔ)言有很多現(xiàn)成的庫(kù),比如PHP通過(guò)Curl庫(kù)上傳文件非常容易。再深入想一想,如果不使用這些庫(kù),怎么上傳文件?可能會(huì)難倒很多人,所以這篇文章簡(jiǎn)單講講文件上傳的原理,其實(shí)就是根據(jù)HTTP協(xié)議的定義,封裝一個(gè)HTTP消息體。
MIME
首先必須先講下MIME(Multipurpose Internet Mail Extensions),它并不是HTTP協(xié)議的一部分,就像我們每個(gè)人都是獨(dú)一無(wú)二的,有自己的屬性,互聯(lián)網(wǎng)上每個(gè)資源也有屬性,比如有些資源是圖片,有些是視頻,有些是HTML頁(yè)面,MIME規(guī)定了每種資源的類(lèi)型,這個(gè)類(lèi)型不是隨便定義的,由IANA負(fù)責(zé)登記和維護(hù)。
說(shuō)的有點(diǎn)難理解,比如你看到一個(gè)URL地址,http://localhost/image.png,我們其實(shí)并不是通過(guò).png后綴判斷資源類(lèi)型的,而是通過(guò)MIME來(lái)獲知該資源類(lèi)型的,這個(gè)圖片的MIME可能就是image/png(至于客戶(hù)端如何知曉資源的MIME類(lèi)型,后面會(huì)講),現(xiàn)在是不是有了點(diǎn)感性的認(rèn)識(shí)了。
MIME類(lèi)型結(jié)構(gòu)如下:
type/subtype
type相當(dāng)于某些類(lèi)型的集合,而subtype相當(dāng)于子類(lèi)型。以image/png為例,image表示圖片類(lèi)型集合,png表示某種類(lèi)型圖片。
讓我們看幾個(gè)比較重要的MIME類(lèi)型:
text/plain text/html application/octet-stream multipart/form-data
其實(shí)本篇文章的主角就是multipart/form-data,再等一等,先別著急,再一次說(shuō)說(shuō)MIME,從它的英文全稱(chēng)來(lái)看,它和mail有關(guān)系,是由mail應(yīng)用定義而來(lái)的,一封郵件由多種資源組成,為了將不同類(lèi)型的資源組成在郵件中,MIME產(chǎn)生了。隨著互聯(lián)網(wǎng)Web的發(fā)展,MIME的作用越來(lái)越多,擴(kuò)展也越來(lái)越多,MIME概念也逐步移到了Web。
Content Type
現(xiàn)在我們定義了每種資源的MIME類(lèi)型,那么客戶(hù)端如何知曉每種資源的MIME類(lèi)型呢?這時(shí)候就要使用Content-Type HTTP Header 頭了,比如我們請(qǐng)求一個(gè)資源,Web服務(wù)器在發(fā)送資源的時(shí)候,發(fā)送了“content-type:image/png” Header 頭,這樣客戶(hù)端就知道該資源是一個(gè)png圖片了。
如果客戶(hù)端發(fā)送了一個(gè) “Content-Type: multipart/form-data;”,代表客戶(hù)端要上傳一個(gè)附件。
也就是說(shuō) Content-Type 后面的值就是一個(gè) MIME 類(lèi)型,聰明的同學(xué)也猜到了,上傳附件和 multipart/form-data MIME 類(lèi)型有關(guān),確實(shí)是!
multipart/form-data
multipart/form-data 這個(gè)MIME類(lèi)型并不是標(biāo)準(zhǔn)的MIME類(lèi)型,而是因?yàn)閃eb的需要擴(kuò)展而來(lái)的,我們?cè)陂_(kāi)發(fā)網(wǎng)頁(yè)的時(shí)候?yàn)榱松蟼饕粋€(gè)文件,會(huì)輸入以下的HTML標(biāo)簽:
關(guān)于HTML表單上傳可以參考 https://www.w3.org/TR/html5/s... 或 RFC 1867(Form-based File Upload in HTML,該RFC已經(jīng)廢棄了)。
那么multipart/form-data表示什么呢?multipart互聯(lián)網(wǎng)上的混合資源,就是資源由多種元素組成,form-data表示可以使用HTML Forms 和 POST 方法上傳文件,具體的定義可以參考RFC 7578。
multipart/form-data結(jié)構(gòu)
說(shuō)了那么多,從HTTP協(xié)議的角度,最后看下文件上傳的HTTP消息體,使用Postman也容易看出,如下:
POST /api.php HTTP/1.1 Host: localhst Cache-Control: no-cache Content-Type: multipart/form-data; boundary=----FormBoundary ------FormBoundary Content-Disposition: form-data; name="file"; filename="file.png" Content-Type: image/png <圖片二進(jìn)制內(nèi)容> ------FormBoundary Content-Disposition: form-data; name="param1" value1 ------FormBoundary Content-Disposition: form-data; name="param2" value2 ------FormBoundary--
消息體什么意思呢,如果你自行想使用代碼實(shí)現(xiàn)文件上傳,要根據(jù)定義自行封裝HTTP消息,接下去我們簡(jiǎn)單描述一下。
Content-Type: multipart/form-data; boundary=——FormBoundary 表示要上傳附件,其中boundary表示分隔符,如果要上傳多個(gè)表單項(xiàng),就要使用boundary分割,每個(gè)表單項(xiàng)由———FormBoundary開(kāi)始,以———FormBoundary結(jié)尾。每一個(gè)表單項(xiàng)又由Content-Type和Content-Disposition組成。
------FormBoundary Content-Disposition: form-data; name="param1" value1 ------FormBoundary
表示普通的一個(gè)表單元素,最重要的是理解 Content-Disposition HTTP 消息頭,其中第一個(gè)參數(shù)總是固定不變的form-data,name表示表單元素屬性名,回車(chē)換行符后面的內(nèi)容就是元素的值。
接下去重點(diǎn)描述和文件有關(guān)的:
------FormBoundary Content-Disposition: form-data; name="file"; filename="file.png" Content-Type: image/png
<圖片二進(jìn)制內(nèi)容>
------FormBoundary
其中多了一個(gè)filename參數(shù),表示文件名,Content-Type 告訴服務(wù)器這是一個(gè)圖片,內(nèi)容就是圖片的二進(jìn)制數(shù)據(jù)。
其實(shí)Content-Disposition這個(gè)HTTP header頭用途也很廣泛,在本文就不重點(diǎn)描述了。
其實(shí)要自行封裝文件上傳,最好的辦法就是用自己熟悉的開(kāi)發(fā)語(yǔ)言實(shí)現(xiàn)一下,這樣印象才更深刻,希望這篇文章對(duì)你有用。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/53571.html
摘要:當(dāng)用戶(hù)完成選擇文件動(dòng)作時(shí),提交子頁(yè)面中的。從此我們上傳文件就歡欣鼓舞的來(lái)找了。因?yàn)榈暮诵氖菍?duì)象,異步的實(shí)現(xiàn)是通過(guò)一個(gè)對(duì)象,一般簡(jiǎn)稱(chēng)該對(duì)象對(duì)。這些回答基于自己理解,如有不妥,希望路過(guò)的大神輕噴,指正。 背景 平時(shí)工作中經(jīng)常會(huì)遇到需要上傳文件的情況,如果你用ant design 或者element ,它們都提供了上傳的組件。 我們分別來(lái)看一下element 和 antd 手動(dòng)上傳怎么處理:...
摘要:歡迎來(lái)我的個(gè)人站點(diǎn)性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開(kāi)啟性能優(yōu)化之旅高性能滾動(dòng)及頁(yè)面渲染優(yōu)化理論寫(xiě)法對(duì)壓縮率的影響唯快不破應(yīng)用的個(gè)優(yōu)化步驟進(jìn)階鵝廠大神用直出實(shí)現(xiàn)網(wǎng)頁(yè)瞬開(kāi)緩存網(wǎng)頁(yè)性能管理詳解寫(xiě)給后端程序員的緩存原理介紹年底補(bǔ)課緩存機(jī)制優(yōu)化動(dòng) 歡迎來(lái)我的個(gè)人站點(diǎn) 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開(kāi)啟性能優(yōu)化之旅 高性能滾動(dòng) scroll 及頁(yè)面渲染優(yōu)化 理論 | HTML寫(xiě)法...
摘要:歡迎來(lái)我的個(gè)人站點(diǎn)性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開(kāi)啟性能優(yōu)化之旅高性能滾動(dòng)及頁(yè)面渲染優(yōu)化理論寫(xiě)法對(duì)壓縮率的影響唯快不破應(yīng)用的個(gè)優(yōu)化步驟進(jìn)階鵝廠大神用直出實(shí)現(xiàn)網(wǎng)頁(yè)瞬開(kāi)緩存網(wǎng)頁(yè)性能管理詳解寫(xiě)給后端程序員的緩存原理介紹年底補(bǔ)課緩存機(jī)制優(yōu)化動(dòng) 歡迎來(lái)我的個(gè)人站點(diǎn) 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開(kāi)啟性能優(yōu)化之旅 高性能滾動(dòng) scroll 及頁(yè)面渲染優(yōu)化 理論 | HTML寫(xiě)法...
摘要:歡迎來(lái)我的個(gè)人站點(diǎn)性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開(kāi)啟性能優(yōu)化之旅高性能滾動(dòng)及頁(yè)面渲染優(yōu)化理論寫(xiě)法對(duì)壓縮率的影響唯快不破應(yīng)用的個(gè)優(yōu)化步驟進(jìn)階鵝廠大神用直出實(shí)現(xiàn)網(wǎng)頁(yè)瞬開(kāi)緩存網(wǎng)頁(yè)性能管理詳解寫(xiě)給后端程序員的緩存原理介紹年底補(bǔ)課緩存機(jī)制優(yōu)化動(dòng) 歡迎來(lái)我的個(gè)人站點(diǎn) 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開(kāi)啟性能優(yōu)化之旅 高性能滾動(dòng) scroll 及頁(yè)面渲染優(yōu)化 理論 | HTML寫(xiě)法...
閱讀 3182·2021-09-24 10:26
閱讀 3450·2021-09-23 11:54
閱讀 4819·2021-09-22 15:33
閱讀 2324·2021-09-09 09:33
閱讀 1767·2021-09-07 10:10
閱讀 1024·2019-08-30 11:09
閱讀 2991·2019-08-29 17:13
閱讀 1086·2019-08-29 12:35