前言
作為前端開發,工作中少不了與介面請求打交道。對於常見的content-type,也能說上來幾個,感覺還算了解。直到有一天,我要在檢視google的批量介面合併時發現Content-Type: multipart/mixed以及Content-Type: application/http時,有點措手不及。趕緊深入研究下Content-Type相關內容來彌補下自己的不足,從前端的角度來看看Content-Type。
Content-Type
Content-Type:實體頭部用於指示資源的MIME型別。如果未指定 ContentType,預設為text/html 有兩種場景: 在請求中 (如POST 或 PUT),客戶端告訴伺服器實際傳送的資料型別。
在響應中,Content-Type標頭告訴客戶端實際返回的內容的內容型別。瀏覽器會在某些情況下進行MIME查詢,並不一定遵循此標題的值; 為了防止這種行為,可以將標題 X-Content-Type-Options 設定為 nosniff。
簡而言之就是標識資源或者所需資源的MIME型別。
句法如下:
Content-Type: text/html; charset=utf-8
Content-Type: multipart/form-data; boundary=something
複製程式碼
引數一般media-type、charset、boundary三種。 我們的關注點在於media-type的取值以及其適用場景。
media-type
更多的是作為MIME type( Multipurpose Internet Mail Extensions)出現,即多用途Internet郵件擴充套件。
其目的是用一種標準化的方式來標識文件的性質和格式。
瀏覽器通常使用MIME型別(而不是副檔名)來確定如何處理文件;
因此伺服器設定正確以將正確的MIME型別附加到響應物件的頭部是非常重要的。
結構
MIME 組成結構如下: 由型別與子型別兩個字串中間用'/'分隔而組成。不允許空格存在。對大小寫不敏感,但傳統都是小寫。 允許額外引數,如後面所示:
type/subtype;parameter=value
複製程式碼
其中:
- type對應通用類目,例如:text/video等。
- subtype對應準確的子類,例如text下面細分為plain(純文字)、html(html原始碼)、calendar(.ics)檔案等。
- parameter可選一般是charset或者bundaary等。
Types
類目包括兩種型別:獨立型別和Multipart型別。
獨立型別
獨立型別指只代表一個單獨的檔案或者媒體的型別,表明了對檔案的分類。 常見型別和例項如下:
- text 文字資料包括一些人類可讀的內容或者原始碼。例如:text/plain, text/csv, text/html.
- application 資料為二進位制的一種,例如application/octet-stream,application/pdf,application/pkcs8,application/zip.
- audio 音訊或者音樂資料,例如audio/mpeg, audio/vorbis
- video 視訊資料或者檔案,例如video/mp4
- image 影象或圖形資料,包括點陣圖和向量靜止影象以及靜止影象格式的動畫版本。例如image/gif, image/png, image/jpeg, image/bmp, image/webp, image/x-icon
Multipart型別
Multipart型別指明被分為幾部分的一種文件的類目,且經常有不同的MIME型別。也可以用來表示屬於相同事物的多個且獨立的檔案,這些獨立的檔案構成一個複雜的文件。在電子郵件場景中常見。
有兩種Multipart型別:message和multipart。
- message 一個包括其他資訊的訊息,常用於下面的場景,例如指明一個郵件包含轉發資訊或者在多種資訊的情況下,允許以chunk的形式傳送資料量很大的資訊。包括message/rfc822和message/partial
- multipart
由多個不同MIME型別元件構成的資料,例如 multipart/form-data(使用FormData API生成的資料)
看完了基本定義,下面看看常見的型別及使用場景。
常見型別及使用場景
靜態資源、圖片、媒體類
對於靜態資源、圖片和媒體類,也就是text、image、video等比較清晰明瞭,不再詳細描述。
application類
-
application/json
隨著json這種輕量級的資料互動格式的流行,特別是和指令碼互動的便利,使得在前後介面中,越來越多采用json格式。對於http協議來說,最終傳輸的還是字元。這裡不再多進行描述。
-
application/x-www-form-urlencoded 作為表單提交中預設的型別,其表明資料以標準的編碼格式被編碼為鍵值對。 資料被編碼成以 '&' 分隔的鍵-值對, 同時以 '=' 分隔鍵和值. 非字母或數字的字元會被 percent-encoding: 這也就是為什麼這種型別不支援二進位制資料的原因 (應使用 multipart/form-data 代替).
我們以新浪為例,可以看到其請求報文(formdata那裡選擇,view source可以看得比較清楚):
-
multipart/form-data 這裡為了對比,就也放到這裡來說了。
一般用於涉及檔案的表單提交,用於post請求,其格式如下:Content-Type: multipart/form-data; boundary=aBoundaryString 複製程式碼
其中boundary指明瞭請求體中每部分的分割符(對於multipart的類目,都會存在該欄位,以區分請求體中資料的分割),其請求體中則是對應表單每部分的內容。每部分都會有自己的請求體和相關內容。
例如如下的文件結構:
<form action="http://localhost:8000/" method="post" enctype="multipart/form-data">
<input type="text" name="myTextField">
<input type="checkbox" name="myCheckBox">Check</input>
<input type="file" name="myFile">
<button>Send the file</button>
</form>
複製程式碼
其請求資訊如下:
POST / HTTP/1.1
Host: localhost:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
// 以 ---------------------------8721656041911415653955004498 作為分割符
Content-Type: multipart/form-data; boundary=---------------------------8721656041911415653955004498
Content-Length: 465
-----------------------------8721656041911415653955004498
// 分段一 文字相關資訊
Content-Disposition: form-data; name="myTextField"
// 對應value
Test
-----------------------------8721656041911415653955004498
// checkbox
Content-Disposition: form-data; name="myCheckBox"
on
-----------------------------8721656041911415653955004498
// 檔案
Content-Disposition: form-data; name="myFile"; filename="test.txt"
Content-Type: text/plain
Simple file.
-----------------------------8721656041911415653955004498--
複製程式碼
-
application/javascript application/x-javascript text/javascript
對於js檔案,常見MIME型別為text/javascript,但是前兩種應該會有見到過。三者之間多少還是有點區別的。
傳統的js程式對應的MIME型別為text/javascript,其他的還有"application/x-javascript"(x字首表示這是實驗性型別), 因為text/javascript是最常見的型別,所以RFC4329定義了“text/javascript”。不過,js檔案實際上並不是真正的文字型別,因此推出了application/javascript型別,不過現行的支援性並不好,所以常常會用application/x-javascript來代替。 -
application/zip application/gzip
zip 對應zip壓縮檔案,gzip是若干種檔案壓縮程式的簡稱,通常指GNU計劃的實現,此處的gzip代表GNU zip。 -
application/http
這一種大家可能就不常見了,從型別可以知道,是http請求,但具體用途還是要翻下規範才能找到的。
此型別包含的http請求包含在binary訊息體中,在郵件協議傳輸中需要指明Content-Transfer-Encoding。
在批量處理請求時會遇到,其表現如下:
--batch_0123456789
Content-Type: application/http
Content-ID:
// 必須的欄位,表明傳送內容的編碼格式 即二進位制流
Content-Transfer-Encoding: binary
POST https://www.googleapis.com/analytics/v3/management/accounts/XXXXXX/webproperties/UA-XXXXXX-1/customDimensions
Content-Type: application/json
Content-Length: 68
{
"name": "Campaign Group",
"scope": "SESSION",
"active": true
}
複製程式碼
multipart型別
正如上文所述,multipart一般對應單個訊息頭對應多個訊息體。 常見語法如下:
Content-Type: multipart/mixed; boundary=gc0p4Jq0M2Yt08jU534c0p
複製程式碼
其中boundary欄位是必須的,用於區分訊息體中的資料邊界,一般是兩個'-'的格式作為該端的開頭,例如:
--gc0p4Jq0M2Yt08jU534c0p
複製程式碼
我們主要關注的也就是下面幾種:
-
multipart/form-data 見上面application部分。下面這幾部分可能不是那麼常見,不過還是可以瞭解一下,以免遇到的時候懵逼。
-
multipart/mixed
該型別用於,訊息體由多個獨立的部分組成且想連續的展示。並且子資料型別有任一種無法被識別(此處指被瀏覽器直接識別的型別,例如text等)的型別時,都應該為mixed。
概括而言就是該郵件有二進位制內容,非可以直接識別的內容
例如:
POST /batch/farm/v1 HTTP/1.1
Authorization: Bearer your_auth_token
Host: www.googleapis.com
Content-Type: multipart/mixed; boundary=batch_foobarbaz
Content-Length: total_content_length
--batch_foobarbaz
// 子內容為http請求 不過是boundary編碼過的
Content-Type: application/http
Content-ID: <item1:12930812@barnyard.example.com>
GET /farm/v1/animals/pony
--batch_foobarbaz
Content-Type: application/http
Content-ID: <item2:12930812@barnyard.example.com>
PUT /farm/v1/animals/sheep
Content-Type: application/json
Content-Length: part_content_length
If-Match: "etag/sheep"
{
"animalName": "sheep",
"animalAge": "5"
"peltColor": "green",
}
--batch_foobarbaz
Content-Type: application/http
Content-ID: <item3:12930812@barnyard.example.com>
GET /farm/v1/animals
If-None-Match: "etag/animals"
--batch_foobarbaz--
複製程式碼
這裡訊息體中的內容就是http請求,在google批量介面協議中用使用。
- multipart/alternative
該型別與mixed的語法相同,但語義不同。其表明,訊息體中的不同部分應該是相同資訊的不同版本。即內容相同傳輸型別不同,以適應不同的接受者。
還是舉例:
From: Nathaniel Borenstein <nsb@bellcore.com>
To: Ned Freed <ned@innosoft.com>
Subject: Formatted text mail
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary=boundary42
--boundary42
Content-Type: text/plain; charset=us-ascii
...plain text version of message goes here....
--boundary42
Content-Type: text/richtext
.... richtext version of same message goes here ...
--boundary42
Content-Type: text/x-whatever
.... fanciest formatted version of same message goes here
...
--boundary42--
複製程式碼
假如使用者的系統可以識別 text/x-whatever 型別,那麼其將會只看到這一部分。不同的使用者看到什麼內容取決於其系統支援何種型別。
結束語
參考
developers.google.com/drive/api/v…
developer.mozilla.org/en-US/docs/…
www.ruanyifeng.com/blog/2008/0…
www.w3.org/Protocols/r…
到這裡常見的content-type就介紹完了,感謝以上參考文章,此外水平有限可能有錯誤之處歡迎指出。對於前端同學來說,網路請求也是我們需要關注的部分,提升深度的同時也要注意落款廣度,希望對有需要的同學有所裨益。