透過Restful API傳送檔案

通常如果我們有傳送檔案的需求時,在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/plainimage/pngimage/gif, or multipart/mixed. If a parameter specifies multiple files, you must specify the multipart/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

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *