HTTP系列--Content type

其他網址

HTTP content-type | 菜鳥教程

POST提交數據之---Content-Type的理解; - 龍恩0707 - 博客園

簡介

        form表單中可以定義enctype屬性,該屬性的含義是在發送到服務器之前應該如何對錶單數據進行編碼。默認的情況下,表單數據會編碼爲"application/x-www-form-unlencoded"。

<form method="post" action="show-data.php" enctype="multipart/form-data">
	...
</form>

Content-Type有數百個,下面例舉了一些常見的

 常見的媒體格式類型如下:

  • text/html : HTML格式
  • text/plain :純文本格式
  • text/xml : XML格式
  • image/gif :gif圖片格式
  • image/jpeg :jpg圖片格式
  • image/png:png圖片格式

以application開頭的媒體格式類型:

  • application/xhtml+xml :XHTML格式
  • application/xml: XML數據格式
  • application/atom+xml :Atom XML聚合格式
  • application/json: JSON數據格式
  • application/pdf:pdf格式
  • application/msword : Word文檔格式
  • application/octet-stream : 二進制流數據(如常見的文件下載)
  • application/x-www-form-urlencoded : <form encType=””>中默認的encType,form表單數據被編碼爲key/value格式發送到服務器(表單默認的提交數據的格式)

另外一種常見的媒體格式是上傳文件之時使用的:

  • multipart/form-data : 需要在表單中進行文件上傳時,就需要使用該格式

上面的Content-Type,我們只認得就好,但是下面有4種是需要我們清楚他們的區別及牢記在心的。

application/x-www-form-urlencoded

簡介

特點

  1. 支持GET/POST等方法。
    如果請求類型type是GET的話,那麼格式化的字符串將直接拼接在url後發送到服務端; 如果請求類型是POST, 那麼格式化的字符串將放在http body的Form Data中發送。
  2. 所有數據變成鍵值對的形式 key1=value1&key2=value2的形式
  3. 特殊字符需要轉義成utf-8編號,如空格會變成 %20;
  4. 所有瀏覽器都支持

作用:

1:最常見的POST提交數據方式。
2:原生form默認的提交方式(可以使用enctype指定提交數據類型)。
3:jquery,zepto等默認post請求提交的方式。

form表單中post默認提交方式的數據

<!DOCTYPE html>
<html>
<head>
  <title></title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
</head>
<body>
  <div id="app">
    <form action="http://www.example.com" method="POST">
      <p>username: <input type="text" name="fname" /></p>
      <p>age: <input type="text" name="age" /></p>
      <input type="submit" value="提交" />
    </form>
  </div>
</body>
</html>

請求轉化:

使用ajax的方式提交

<!DOCTYPE html>
<html>
<head>
  <title></title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
  <script type="text/javascript" src="https://tugenhua0707.github.io/html5UploadImage/js/jquery.js"></script>
</head>
<body>
  <div id="app">
    <div class="btn">發送post請求</div>
  </div>

  <script>
    var obj = {
      "name": 'CntChen',
      "info": 'Front-End',
    };
    $('.btn').click(function() {
      $.ajax({
        url: 'www.example.com',
        type: 'POST',
        dataType: 'json',
        data: obj,
        success: function(d) {
          
        }
      })
    });
  </script>
</body>
</html>

 轉化之後:

multipart/form-data

簡介

特點

  1. 使用表單上傳文件時,必須指定表單的 enctype屬性值爲 multipart/form-data。
  2. 請求體被分割成多部分,每部分使用 --boundary分割;

注意事項

        此時用request.getParameter是取不到數據的,這個時候需要通過request.getInputStream來獲取數據。這時取到的是一個InputStream,無法直接取到指定的表單項。但是有很多開源的組件可以直接利用,比如apache的fileupload組件。通過這些開源的upload組件,提供的api,就可以直接從request中取得指定的表單項:

ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> list = upload.parseRequest(request);

上面的代碼中,接下來就可通過遍歷list獲取參數了。 

實例

<!DOCTYPE html>
<html>
<head>
  <title></title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
</head>
<body>
  <div id="app">
    <form action="http://www.example.com" method="POST" enctype="multipart/form-data">
      <p>username: <input type="text" name="fname" /></p>
      <p>age: <input type="text" name="age" /></p>
      <input type="submit" value="提交" />
    </form>
  </div>
</body>
</html>

 轉化之後

application/json

簡介

問題引出

        http請求中,ContentType都是默認的值 application/x-www-form-urlencoded, 這種編碼格式的特點是:name/value值對,每組之間使用&連接,而name與value之間是使用 = 連接,比如 key=xxx&name=111&password=123456; 鍵值對一般的情況下是沒有什麼問題的,是很簡單的json形式,比如如下:

{
  a: 1,
  b: 2
}

它會解析成 a=1&b=2這樣的,但是在一些複雜的情況下,比如需要傳一個複雜的json對象,也就是對象嵌套數組的情況下,比如如下代碼:

{
  obj: [
    {
      "name": 111,
      "password": 22
    }
  ]
}

        這樣複雜的對象,application/x-www-form-urlencoded這種形式傳遞的話, 會被解析成 obj[0]['name']=111&obj[0].['password']=2這樣的。然後再轉成json形式;

        對於一些複雜的數據對象,對象裏面再嵌套數組的話,建議使用application/json傳遞比較好,開發那邊也會要求使用application/json。因爲他們那邊不使用application/json的話,使用默認的application/x-www-form-urlencoded傳遞的話,開發那邊先要解析成如上那樣的,然後再解析成json對象,如果對於比上面更復雜的json對象的話,那麼他們那邊是很難解析的,所以直接json對象傳遞的話,對於他們來說更簡單。

        通過json的形式將數據發送給服務器。json的形式的優點是它可以傳遞結構複雜的數據形式,比如對象裏面嵌套數組這樣的形式等。

實例

<!DOCTYPE html>
<html>
<head>
  <title></title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
  <script type="text/javascript" src="https://tugenhua0707.github.io/html5UploadImage/js/jquery.js"></script>
</head>
<body>
  <div id="app">
    <div class="btn">發送post請求</div>
  </div>

  <script>
    $('.btn').click(function() {
      $.ajax({
        url: 'http://www.example.com',
        type: 'POST',
        dataType: 'json',
        contentType: 'application/json',
        data: JSON.stringify({a: [{b:1, a:1}]}),
        success: function(d) {
          
        }
      })
    });
  </script>
</body>
</html>

如上代碼,在瀏覽器運行後,發現跨域了,如下圖所示:

理解ajax跨域設置 ContentType: application/json

        在使用ajax跨域請求時,如果設置Header的ContentType爲 application/json,它會發兩次請求,第一次先發Method爲OPTIONS的請求到服務器,這個請求會詢問服務器支持那些請求方法(比如GET,POST)等。如果這個請求支持跨域的話,就會發送第二個請求,否則的話在控制檯會報錯,第二個請求不會請求。如下我們做個簡單的demo,不跨域的如下:

<!DOCTYPE html>
<html>
<head>
  <title></title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
  <script type="text/javascript" src="https://tugenhua0707.github.io/html5UploadImage/js/jquery.js"></script>
</head>
<body>
  <div id="app">
    <div class="btn">發送post請求</div>
  </div>

  <script>
    $('.btn').click(function() {
      $.ajax({
        url: 'http://localhost:8081/api.json',
        type: 'POST',
        dataType: 'json',
        contentType: 'application/json',
        data: JSON.stringify({a: [{b:1, a:1}]}),
        success: function(d) {
          
        }
      })
    });
  </script>
</body>
</html>

如下圖所示(json格式提交的數據會顯示 Request Payload):

application/xml 和 text/xml

        XML 麻煩,推薦用 JSON 。

        XML(Extensible Markup Language) 是 SGML(Standard Generalized Markup Language)的一個子集。SGML 也分配了媒體類型( text/sgml 和 application/sgml),但兼容性較差。XML 有兩種 MIME 媒體類型:text/xml 和 application/xml。

RFC2376 文檔 定義了application/xml 和 text/xml 媒體類型。
RFC7303 文檔 也定義了application/xml 媒體類型。
RFC3023 文檔 一次定義了application/xml 和 text/xml 等所有的 XML 相關媒體類型。

application/xml 媒體類型

推薦使用。如果 MIME 用戶代理或 Web 用戶代理不支持這個媒體類型,會轉爲 application/octet-stream,當做二進制流來處理。application/xml 實體默認用 UTF-8 字符集。Content-type: application/xml; charset="utf-8" 或 <?xml version="1.0" encoding="utf-8"?> 都可以生效。

text/xml 媒體類型

如果 MIME 用戶代理或 Web 用戶代理不支持這個媒體類型,會將其視爲 text/plain,當做純文本處理。text/xml 媒體類型限制了 XML 實體中可用的編碼類型(例如此時支持 UTF-8 但不支持 UTF-16,因爲使用 UTF-16 編碼的文本在處理 CR,LF 和 NUL 會導致異常轉換)。text/xml 實體在 XML 頭指定編碼格式無效,必須在 HTTP 頭部的 Content-Type: 中指定纔會生效(例如 <?xml version="1.0" encoding="utf-8"?> 無法設置字符集,Content-Type: text/xml; charset="utf-8" 則可以)。沒有設置字符集時默認使用“us-ascii”字符集。

Content-Type的使用

request 的Content-Type

        一般我們在開發的過程中需要注意客戶端發送請求(Request)時的Content-Type設置,特別是使用ajax的時候,如果設置得不準確,很有可能導致請求失敗。比如在spring中,如果接口使用了@RequestBody,spring強大的自動解析功能,會將請求實體的內容自動轉換爲Bean,但前提是請求的Content-Type必須設置爲application/json,否正就會返回415錯誤。
注:415 錯誤是 Unsupported media type,即不支持的媒體類型。

建議:

    如果是一個restful接口(json格式),一般將Content-Type設置爲application/json; charset=UTF-8;
    如果是文件上傳,一般Content-Type設置爲multipart/form-data
    如果普通表單提交,一般Content-Type設置爲application/x-www-form-urlencoded

response的Content-Type

        服務端響應(Response)的Content-Type最好也保持準確,雖然一般web開發中,前端解析響應的數據不會根據Content-Type,並且服務端一般能自動設置準確的Content-Type,但是如果亂設置某些情況下可能會有問題,比如導出文件,打開圖片等。如果在spring項目裏使用@ResponseBody,spring會將響應的Content-Type設置爲application/json;charset=UTF-8;,可能會導致文件無法導出,需要注意下。

response的Content-Type設置建議:

    一般情況下不需要顯示設置;
    如果是文件導出,Content-Type 設置爲 multipart/form-data,並且添加一個Content-Disposition設置爲attachment;fileName=文件.後綴。
    注:Content-Disposition是Content-Type的擴展,告訴瀏覽器彈窗下載框,而不是直接在瀏覽器裏展示文件。因爲一般瀏覽器對於它能夠處理的文件類型,如txt,pdf 等,它都是直接打開展示,而不是彈窗下載框。

下面的一個設置response的Content-Type的例子:

    未準確設置response的Content-type的情況,客戶端將json數據當成普通文本
    content-type →text/html;charset=UTF-8

    準確設置response的Content-type的情況,客戶端將json數據自動解析
    content-type →application/json;charset=UTF-8

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章