通常如果我們有傳送檔案的需求時,在http的世界裡,我們可以透過restful api定義的兩種content-type來實作:
application/x-www-form-urlencoded
multipart/form-data
雖然說,之前在工作中也有過一些使用上的經驗,但趁這次工作上又需要碰到,所以來做點筆記。
application/x-www-form-urlencoded
The
application/x-www-form-urlencoded
content type describes form data that is sent in a single block in the HTTP message body. Unlike the query part of the URL in a GET request, the length of the data is unrestricted.
從這裡可以看到,當如果我們需要透過http 傳送單一檔案時,我們可以在body中放入我們需要傳送的檔案;而使用這種方式傳送檔案時,其內容必須遵循以下的encoding rules:
* Control names and values are escaped. Space characters are replaced by `+’, and then reserved characters are escaped as described in [RFC1738], section 2.2: Non-alphanumeric characters are replaced by `%HH’, a percent sign and two hexadecimal digits representing the ASCII code of the character. Line breaks are represented as “CR LF” pairs (i.e., `%0D%0A’).
* The control names/values are listed in the order they appear in the document. The name is separated from the value by `=’ and name/value pairs are separated from each other by `&’.
從stackoverflow的這篇文章來看,一般使用這種方式傳送檔案時,平均會增加至少33%
的額外流量,所以並不是一個很有效率的方法。
multipart/form-data
In the
multipart/form-data
content type, the HTTP message body is divided into parts, each containing a discrete section of data.Each message part requires a header containing information about the data in the part. Each part can contain a different content type; for example,
text/plain
,image/png
,image/gif
, ormultipart/mixed
. If a parameter specifies multiple files, you must specify themultipart/mixed
content type in the part header.
這種類型的content-type,定義了client可以在message body中傳送多個不同的檔案,此外,我們必須為每種檔案設定其檔案類型。
在encoding的部分,這裡被沒有強制使用base64,而是讓客戶端可以指定conding的方式。
根據w3c的文件中提到,multipart 是較適合用來傳送binary file或一些non-ASCII的檔案。
application/octet-stream
通常這種類型的content-type是用來給瀏覽器下載檔案時使用,瀏覽器收到這類型的content-type時,預設就會直接下載到本地端。
但在stackoverflow的這篇文章中有提到,我們其實可以直接透過POST 直接設定content-type 為application/octet-stream
,並且在加上以下的header 設定就可以直接指定要傳送的檔案。
Connection: close
Content-Type: application/octet-stream
Content-Length: <content-size>
結論
multipart/form-data
已發展多年了,且從文件上來看,在最初定義時就是為了傳送二進制的檔案類型,所以我們若有這方面的需求時,應該盡量使用這個content-type。- 如果我們的需求只是傳送單一的小檔案,且又可以使用base64 encoding時,使用
application/x-www-form-urlencoded
也不失為另一個可考慮的選項。
Reference
- https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2
- https://www.microfocus.com/documentation/idol/IDOL_12_0/MediaServer/Guides/html/English/Content/Shared_Admin/_ADM_POST_requests.htm
- https://stackoverflow.com/questions/49580085/is-there-a-size-limit-to-individual-fields-in-http-post
- https://stackoverflow.com/questions/4007969/application-x-www-form-urlencoded-or-multipart-form-data