前端培訓-初級階段-場景實戰(2019-06-06)-Content-Type對照表及日常使用

linong發表於2019-06-03

前端最基礎的就是 HTML+CSS+Javascript。掌握了這三門技術就算入門,但也僅僅是入門,現在前端開發的定義已經遠遠不止這些。前端小課堂(HTML/CSS/JS),本著提升技術水平,打牢基礎知識的中心思想,我們開課啦(每週四)。

axios 日常使用上,感覺不如 $.ajax 但是我之前使用的時候不是改入參就是改方法反正是都解決了。
我也知道問題出在 content-type 上。
就是記不住,這不前幾天後臺專案起了個新的服務。
之前用的構建開發工具用的是 proxy 代理,不知道有老哥用過沒,好幾年前初次開發的時候就不更新了,還有 bug
索性換 axios 代理一下吧,然後報錯了。好吧,我的鍋,我認真總結,保證我不忘了。

今天講什麼?

  1. content-type 是什麼
  2. MIME 對照表
  3. axios 為什麼感覺不如 $.ajax
  4. 帶你領略 axios 正確開啟方式

content-type 是什麼

Content-Type 實體頭部用於指示資源的 MIME型別 media type
在響應中,用來描述服務端實際傳送給客戶端的資料的型別
在請求中,比如 POST請求,是指客戶端給伺服器實際傳送的資料的型別
雙方根據這個值,來選擇適合的方式解析資料。

MIME 型別組成方式

type/subtype,如application/jsontext/htmltext/plain
對大小寫不敏感,但是習慣寫小寫

content-type 組成方式

Content-Type:media-type; charset,如Content-Type: text/html; charset=utf-8

表單中的應用

<form action="/" method="post" enctype="multipart/form-data"> 想上傳檔案的時候
<form action="/" method="post" enctype="application/x-www-form-urlencoded"> 預設
為什麼想上傳檔案不能用第二個呢?帶著你的問題往後看吧

MIME 對照表

Media Types -全量的對照表

MIME 分類

type關鍵詞 描述 示例
text 文字。複製貼上的裡面常見。 text/html html頁面, text/css css檔案,text/plain 通用文字(預設格式)
image 圖片。input.files[0].type 返回的時候用於判斷型別。input accept="image/*" 允許選擇所有圖片檔案 image/png png圖片, image/jpeg jpg圖片
audio 音訊。同上 audio/wav,audio/mpeg mp3檔案
video 影片。同上 video/mp4 MP4檔案
application 二進位制資料 application/octet-stream 通用型別(預設格式),application/pdf
multipart 複合型別 multipart/form-data

常見 MIME

key 描述
application/octet-stream 預設值,或者可以理解為未知的應用程式檔案瀏覽器會像對待設定了 HTTP 頭 Content-Disposition 值為 attachment 的檔案一樣來對待這類檔案。(微信下載檔案)
text/html 可以理解為 html、xml 檔案。
text/plain 預設值,也可以理解為未知格式的文字檔案。文字檔案嘛,沒格式就只看字也不是啥大問題
image/png 常見圖片型別,一般上傳圖片的時候判斷
image/jpeg 常見圖片型別,一般上傳圖片的時候判斷
image/gif 常見圖片型別,一般上傳圖片的時候判斷
multipart/byteranges 用於把部分的響應報文傳送回瀏覽器。常見於請求影片資源返回206狀態碼
application/json JSON 格式
multipart/form-data 用於帶檔案上傳的表單提交。作為多部分文件格式,由邊界線(一個由'--'開始的字串)劃分出的不同部分組成。每一部分有自己的實體,以及自己的 HTTP 請求頭,Content-DispositionContent-Type
application/x-www-form-urlencoded 普通的 get&post 請求。資料被編碼為鍵/值對(a=1&b=2)這是標準的編碼格式。

axios 為什麼感覺不如 $.ajax

(同樣程式碼 jquery 好使,axios 不好使,axios 有 bug 吧)-這個應該是我聽到最多的吐槽了。測試地址

axios 與 $.ajax 設計思路、或者說歷史場景

  1. jquery 非常棒,他存在解決了各個瀏覽器版本不一致的問題,提供了統一的 api,極大的簡化了我們的操作。
  2. axios 擁抱現代瀏覽器,提供跨平臺(Node發請求)、 Promise等。

get 請求

對於 get 請求其實沒有太多說的,請求的引數會拼在 url 上,如 https://www.lilnong.top/CORS/lnong?a=1&b=2,其中 a=1&b=2 就是帶過去的引數

同樣兩個使用,我們會發現 axios 的沒有帶過去引數。
clipboard.png
clipboard.png
這個時候兄弟們就開始說,我寫了為什麼傳不過去。垃圾垃圾。針對上面的問題兄弟們罵完之後,還是要解決問題的。

  1. 手動拼寫,兄弟也是虎的可以
    clipboard.png
  2. qs$.param({a:1,b:2}) 等類庫解決處理問題,然後手動拼接
  3. 正確答案(axios 是使用 params 來傳送 get 的資料的)
    clipboard.png

post 請求

clipboard.png
對於 post 請求來說就有好幾種情況了

  1. application/x-www-form-urlencoded 這種情況等於把 get 方式的引數拿到 請求體中存放。編譯格式是一模一樣的。
  2. application/json 請求體中就是如下的JSON字串{a:1,b:2}
  3. multipart/form-data 請求體中就是這種塊的結構。
    clipboard.png

好,那我們接著看兄弟們為什麼要吐槽。同樣,我 ajax 怎麼好使,axios ****
clipboard.png

  1. data 不行,我們換 params,嗯這裡其實分為兩個情況

    1. 後臺大哥說收到了,嗯,post 也是 params的結論就出來了
    2. 過幾天另一個後臺大哥說收不到。很奇怪,又開始揪頭髮。
    3. 這裡說一下為什麼有的時候能收到,有的時候不行。首先 params 帶過去的引數會拼寫在 url 上。如果嚴格來按規定做的話,他就是拿body 的資訊就導致拿不到。不按規定來,url的構建一次,body的覆蓋一次,就導致拿到了。
  2. 有的人比較機靈,換 params 發現不怎麼好使,突然發現官網的例子,我來試一試。後臺大哥怎麼還收不到?這裡其實 content-type 被改成了 application/json。一般來說老後臺都不會適配這種格式。axios({method:'post'}) 也是這種格式
    clipboard.pngclipboard.png
  3. 沒辦法了?嗯,他們又開始自己拼接。嗯,這次有混過去了
    clipboard.png
  4. transformRequest 大法,我這個方法裡面,給他處理一番。
    clipboard.png
  5. FormData 大法好,精準識別,也算是正確的表單提交。
    clipboard.png
  6. URLSearchParams 方案等同於 Qs 的類庫,只不過是瀏覽器支援的,當然相容性也不怎麼樣
    clipboard.png

帶你領略 axios 正確開啟方式

  1. 使用 get 要用 params 來傳送請求
  2. 使用 post 要用 data 來傳送請求

    1. 預設為 application/json 格式
    2. 可以透過 FormData 來進行修改
    3. 更建議全域性 transformRequest 的方案
  3. axios 支援 Promise

    axios.get('/user?ID=12345')
      .then(function (response) {
        console.log(response);
      })
      .catch(function (error) {
        console.log(error);
      });
  4. axios 支援 Node 環境
  5. 配置預設值,方案1更痛快,可以增加一些通用的 headers

    1. 全域性的 axios 預設值

        axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
    2. 例項預設值

        // 建立例項時設定配置的預設值
        var instance = axios.create({
          baseURL: 'https://api.example.com'
        });
        
        // 在例項已建立後修改預設值
        instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
  6. 攔截器,可以攔截錯誤,進行上報。或者列印日誌。

    // 新增響應攔截器
    axios.interceptors.response.use(function (response) {
        // 對響應資料做點什麼
        return response;
      }, function (error) {
        // 對響應錯誤做點什麼
        return Promise.reject(error);
      });

總結

content-type 很重要,在 req 中是告知伺服器應該用什麼樣的格式去解析資料,rsp 中是讓瀏覽器端去如何解析資料。
根據對應的型別,傳對應的格式,才可以正確的收發。

參考資料

  1. MIME 型別 --MDN
  2. axios --看雲

相關文章