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