POST提交資料之---Content-Type的理解;

龍恩0707發表於2018-04-30

POST提交資料之---Content-Type的理解;

   Content-Type是指http/https傳送資訊至伺服器時的內容編碼型別,contentType用於表明傳送資料流的型別,伺服器根據編碼型別使用特定的解析方式,獲取資料流中的資料。

在網路請求中,常用的Content-Type有如下:
text/html, text/plain, text/css, text/javascript, image/jpeg, image/png, image/gif,
application/x-www-form-urlencoded, multipart/form-data, application/json, application/xml 等。

其中:text/html, text/plain, text/css, text/javascript, image/jpeg, image/png, image/gif, 都是常見的頁面資源型別。

application/x-www-form-urlencoded, multipart/form-data, application/json, application/xml 這四個是ajax的請求,表單提交或上傳檔案的常用的資源型別。

form表單中可以定義enctype屬性,該屬性的含義是在傳送到伺服器之前應該如何對錶單資料進行編碼。預設的情況下,表單資料會編碼為
"application/x-www-form-unlencoded".

enctype常用的屬性值如下:application/x-www-form-unlencoded: 在傳送前編碼所有字元(預設情況下);
multipart/form-data, 不對字元編碼。在使用檔案上傳時候,使用該值。

一:application/x-www-form-urlencoded 主要用於如下:
1.1: 最常見的POST提交資料方式。
1.2:原生form預設的提交方式(可以使用enctype指定提交資料型別)。
1.3:jquery,zepto等預設post請求提交的方式。

1. 首先來看下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>

如下圖所示:

application/x-www-form-urlencoded 是最常用的一種請求編碼方式,支援GET/POST等方法,所有資料變成鍵值對的形式 key1=value1&key2=value2
的形式,並且特殊字元需要轉義成utf-8編號,如空格會變成 %20;

預設的提交方式是 application/x-www-form-urlencoded 編碼提交資料的,在chrome的network皮膚下,預設的請求體是被解析的。展示成formData的形式;

如下是使用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>

如下圖所示:

如上預設提交的 contentType為 application/x-www-form-urlencoded,此時提交的資料將會格式化成:
username=111&age=2;

如果請求型別type是GET的話,那麼格式化的字串將直接拼接在url後傳送到服務端; 如果請求型別是POST, 那麼格式化的字串將放在http body的Form Data中傳送。

二:multipart/form-data
使用表單上傳檔案時,必須指定表單的 enctype屬性值為 multipart/form-data. 請求體被分割成多部分,每部分使用 --boundary分割;

html程式碼如下:

<!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>

如下圖所示:

ajax formdata提交資料請看這篇文章

三: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形式;

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

對於一些複製的資料物件,物件裡面再巢狀陣列的話,建議使用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>

但是如上程式碼,在瀏覽器執行後,發現跨域了,我們看如下截圖所示:

3.1 理解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;

相關文章