用 HTTP 提交數據,基本就這五種方式
網頁開發中,向服務端提交數據是一個基本功能,工作中會大量用 xhr/fetch 的 api 或者 axios 這種封裝了一層的庫來做。
可能大家都寫過很多 http/https 相關的代碼,但是又沒有梳理下它們有哪幾種呢?
其實通過 http/https 向服務端傳遞數據的方式,基本可以分為 5 種:url param、query、form-urlencoded、form-data、json。
url param
Restful 的規范允許把參數寫在 url 中,比如:
- http://guang.zxg/person/1111
這里的 1111 就是路徑中的參數(url param),服務端框架或者單頁應用的路由都支持從 url 中取出參數。
query
通過 url 中 ?后面的用 & 分隔的字符串傳遞數據。比如:
- http://guang.zxg/person?name=guang&age=20
這里的 name 和 age 就是 query 傳遞的數據。
其中非英文的字符和一些特殊字符要經過編碼,可以使用 encodeURLComponent 的 api,或者使用封裝了一層的 qeury-string 庫來處理。
- const queryString = require('query-string');
- queryString.stringify({
- name: '光',
- age: 20
- });
- //?name=%E5%85%89&age=20
通過 URL 傳遞數據的方式就這 2種,后面 3 種是通過 body 傳遞數據的方式。
form-urlencoded
直接用 form 表單提交數據就是這種,它和 query 字符串的方式的區別只是放在了 body 里,然后指定下 content-type 是 application/x-www-form-urlencoded。
因為也是 query 字符串,所以也要用 encodeURIComponent 的 api 或者 query-string 庫處理下。
其實這種設計也很容易理解,get 是把數據拼成 query 字符串放在 url 后面,于是設計表單的 post 提交方式的時候就直接用相同的方式把數據放在了 body 里。
通過 & 分隔的 form-urlencoded 的方式需要對內容做 url encode,如果傳遞大量的數據,比如上傳文件的時候就不是很合適了,因為文件 encode 一遍的話太慢了,這時候就可以用 form-data。
form-data
form data 不再是通過 & 分隔數據,而是用 --------- + 一串數字做為分隔符。因為不是 url 的方式了,自然也不用再做 url encode。
form-data 需要指定 content type 為 multipart/form-data,然后指定 boundary 也就是分割線。
body 里面就是用 boundary 分割線分割的內容。
很明顯,這種方式適合傳輸文件,而且可以傳輸多個文件。
但是畢竟多了一些只是用來分隔的 boundary,所以請求體會增大。
json
form-urlencoded 需要對內容做 url encode,而 form data 則需要加很長的 boundary,兩種方式都有一些缺點。如果只是傳輸 json 數據的話,不需要用這兩種。
可以直接指定content type 為 application/json 就行:
我們平時傳輸 json 數據基本用的是這種。
這三種是通過 body 傳遞數據的方式。
總結
網頁開發中向服務端傳送數據是一個基本功能,常用的方式就 url param、query、form urlencoded、form data、json 這 5 種。
前 2 種是通過 url 傳遞數據的方式(需要對數據做 url encode),后 3 種是通過 body 傳遞數據。
form urlencoded 只是把 query 放在了 body 里,同樣需要對數據做 url encoded,所以處理文件就不合適了。(content type 要指定為 application/x-www-form-urlencoded)
form data 是通過 boundary 分隔內容,不需要做 url encode,所以用來傳文件很合適。但是如果不是傳文件就沒必要用了,因為多了一些 boundary 字符串比較占空間。(content type 要指定為 multipart/form-data)
json 是現在最常用的傳遞數據的方式,既不需要 url encoded,又不需要加沒必要的 boundary。(指定 content type 為 application/json)。
當然,也可以指定別的 content type,比如 application/xml、text/plain 等,但一般不會用。
99% 情況下,我們都是通過這 5 種 http/https 的提交數據的方式和服務端交互的。