axios的post請求傳參問題與post的四種編碼方式

嘗試了一下Express中的post請求,原以為和get請求是一樣的段多。

axios的post請求的官方示例是這樣的:

axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

但是結(jié)果發(fā)現(xiàn)首量,在后端無論如何都沒有返回我需要的數(shù)據(jù)。

原來衩匣,POST方法提交的數(shù)據(jù)有四種編碼方式蕾总。

1.application/x-www-form-urlencoded

這種方式是最常見的POST編碼方式粥航。瀏覽器的原生<form>表單琅捏,如果不設(shè)置enctype屬性,那么最終就會以 application/x-www-form-urlencoded方式提交數(shù)據(jù)递雀。

很多時候柄延,我們用 Ajax 提交數(shù)據(jù)時,也是使用這種方式缀程。例如 JQueryQWrap 的 Ajax搜吧,Content-Type 默認(rèn)值都是「application/x-www-form-urlencoded;charset=utf-8」。

  1. multipart/form-data

我們使用表單上傳文件時杨凑,必須讓 <form> 表單的 enctype 等于 multipart/form-data滤奈。

這種方式一般用來上傳文件,各大服務(wù)端語言對它也有著良好的支持撩满。

上面提到的這兩種 POST 數(shù)據(jù)的方式蜒程,都是瀏覽器原生支持的绅你,而且現(xiàn)階段標(biāo)準(zhǔn)中原生 <form> 表單也只支持這兩種方式(通過 <form> 元素的 enctype 屬性指定,默認(rèn)為 application/x-www-form-urlencoded昭躺。其實(shí) enctype 還支持 text/plain忌锯,不過用得非常少)。

隨著越來越多的 Web 站點(diǎn)领炫,尤其是 WebApp偶垮,全部使用 Ajax 進(jìn)行數(shù)據(jù)交互之后,我們完全可以定義新的數(shù)據(jù)提交方式帝洪,給開發(fā)帶來更多便利似舵。

3 .application/json

現(xiàn)在越來越多的人把它作為請求頭,用來告訴服務(wù)端消息主體是序列化后的 JSON 字符串葱峡。由于 JSON 規(guī)范的流行啄枕,除了低版本 IE 之外的各大瀏覽器都原生支持 JSON.stringify,服務(wù)端語言也都有處理 JSON 的函數(shù)族沃,使用 JSON 不會遇上什么麻煩频祝。

4.text/xml

它是一種使用 HTTP 作為傳輸協(xié)議,XML 作為編碼方式的遠(yuǎn)程調(diào)用規(guī)范脆淹。XML-RPC 協(xié)議簡單常空、功能夠用,各種語言的實(shí)現(xiàn)都有盖溺。它的使用也很廣泛漓糙,如 WordPress 的 XML-RPC Api,搜索引擎的 ping 服務(wù)等等烘嘱。JavaScript 中昆禽,也有現(xiàn)成的庫支持以這種方式進(jìn)行數(shù)據(jù)交互,能很好的支持已有的 XML-RPC 服務(wù)。

相比之下砰逻,get方式的數(shù)據(jù)提交方式(編碼方式)只有一種堕花,就是application/x-www-form-urlencoding

我們的axios用的就是第三種編碼方式,也就是application/json盗棵,但是Express的post默認(rèn)是第一種方式,所以我們就找不到我們要的數(shù)據(jù)了北发。

問題找到了纹因,就要想辦法解決問題。既然是前后端的數(shù)據(jù)編碼方式不一樣琳拨,那么只要想辦法讓他們一樣就行了瞭恰。

首先,把后端的接收格式改成application/json狱庇。在Express中惊畏,我們需要用到一個叫做bodyParser的中間件是牢。

引入body-parser:

$ npm install body-parser --save

基本使用:

var express = require('express')
//獲取模塊
var bodyParser = require('body-parser')

var app = express()

// 創(chuàng)建 application/json 解析
var jsonParser = bodyParser.json()

// 創(chuàng)建 application/x-www-form-urlencoded 解析
var urlencodedParser = bodyParser.urlencoded({ extended: false })

// POST /login 獲取 URL編碼的請求體
app.post('/login', urlencodedParser, function (req, res) {
  if (!req.body) return res.sendStatus(400)
  res.send('welcome, ' + req.body.username)
})

// POST /api/users 獲取 JSON 編碼的請求體
app.post('/api/users', jsonParser, function (req, res) {
  if (!req.body) return res.sendStatus(400)
  // create user in req.body
});
app.listen(3000);

對請求體的四種解析方式:

1. bodyParser.json(options): 解析json數(shù)據(jù)
2. bodyParser.raw(options): 解析二進(jìn)制格式(Buffer流數(shù)據(jù))
3. bodyParser.text(options): 解析文本數(shù)據(jù)
4. bodyParser.urlencoded(options): 解析UTF-8的編碼的數(shù)據(jù)。

最后陕截,bodyParser變量是對中間件的引用驳棱。請求體解析后,解析值都會被放到req.body屬性农曲,所以直接拿出來就行了社搅。

有的時候后端已經(jīng)固定了,沒有辦法只能改前端乳规。

前端:

this.$axios({
    method:"post",
    url:"/api/haveUser",
    headers:{
        'Content-type': 'application/x-www-form-urlencoded'
    },
    data:{
        name:this.name,
        password:this.password
    },
    transformRequest: [function (data) {
        let ret = ''
        for (let it in data) {
          ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'
        }
        return ret
      }],
}).then((res)=>{
    console.log(res.data);
})

其中發(fā)揮關(guān)鍵作用的是headers與transformRequest形葬。其中 headers 是設(shè)置即將被發(fā)送的自定義請求頭。 transformRequest 允許在向服務(wù)器發(fā)送前暮的,修改請求數(shù)據(jù)笙以。這樣操作之后,后臺querystring.parse(decodeURIComponent(data))獲取到的就是類似于{ name: 'w', password: 'w' }的對象冻辩。后臺代碼如下

后端:

app.post("/api/haveUser",function(req,res){
      let haveUser=require("../api/server/user.js");
      req.on("data",function(data){
          let name=querystring.parse(decodeURIComponent(data)).name;
          let password=querystring.parse(decodeURIComponent(data)).password;
          console.log(name,password)
          haveUser(name,password,res);
      });
});

參考文獻(xiàn):
瀏覽器行為:Form表單提交
post提交數(shù)據(jù)的四種編碼方式
Express 中間件----body-parser(五)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末猖腕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子恨闪,更是在濱河造成了極大的恐慌倘感,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咙咽,死亡現(xiàn)場離奇詭異老玛,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)钧敞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門蜡豹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人溉苛,你說我怎么就攤上這事镜廉。” “怎么了炊昆?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵桨吊,是天一觀的道長威根。 經(jīng)常有香客問我凤巨,道長,這世上最難降的妖魔是什么洛搀? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任敢茁,我火速辦了婚禮,結(jié)果婚禮上留美,老公的妹妹穿的比我還像新娘彰檬。我一直安慰自己伸刃,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布逢倍。 她就那樣靜靜地躺著捧颅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪较雕。 梳的紋絲不亂的頭發(fā)上碉哑,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天,我揣著相機(jī)與錄音亮蒋,去河邊找鬼扣典。 笑死,一個胖子當(dāng)著我的面吹牛慎玖,可吹牛的內(nèi)容都是我干的贮尖。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼趁怔,長吁一口氣:“原來是場噩夢啊……” “哼湿硝!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起润努,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤图柏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后任连,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚤吹,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年随抠,在試婚紗的時候發(fā)現(xiàn)自己被綠了裁着。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡拱她,死狀恐怖二驰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情秉沼,我是刑警寧澤桶雀,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站唬复,受9級特大地震影響矗积,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜敞咧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一棘捣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧休建,春花似錦乍恐、人聲如沸评疗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽百匆。三九已至,卻和暖如春呜投,著一層夾襖步出監(jiān)牢的瞬間胧华,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工宙彪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留矩动,地道東北人。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓释漆,卻偏偏與公主長得像悲没,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子男图,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容