Express.js 解析 Post 數據類型的正確姿式

1、概念介紹

一、POST請求:HTTP/1.1 協議規定的 HTTP 請求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 這幾種。其中 POST 通常用來向服務端提交數據。
二、Content-Type是指 http/https發送信息至服務器時的內容編碼類型, Content-Type用於代表發送數據流的類型,服務器根據編碼類型使用特定的解析方式,獲取數據流中的數據。四種常見的 POST 請求的 Content-Type 數據類型:
  • application/x-www-form-urlencoded
  • multipart/form-data
  • application/json
  • text/xml
三、Express.js Express 是一個保持最小規模的靈活的 Node.js Web 應用程序開發框架,爲 Web 和移動應用程序提供一組強大的功能。
本文咱們主要介紹 Post 請求的 4 種 Content-Type 數據類型,以及如何使用 Express 來對每種 Content-Type 類型進行解析。已經將完整的代碼實例上傳到 github,github地址爲: github.com/fengshi123/… ,歡迎 star 。

2、四種POST請求的Content-Type數據類型解析

一、application/x-www-form-unlencoded

最多見的 POST 提交數據的方式,瀏覽器的原生 form 表單,若是不設置 enctype 屬性,那麼最終就會默認以 application/x-www-form-urlencoded 方式提交數據。
1.一、前端請求代碼

var reqParam = "name=jack";
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(reqParam);
複製代碼
1.二、服務端解析代碼

app.post('/urlencoded', bodyParser.urlencoded({extend:true}), function (req, res) {   
  var result = {
     name: req.body.name,       
     sex: '男',        
     age: 15    
  };   
  res.send(result);
});複製代碼
1.三、瀏覽器請求 / 響應截圖
請求:
響應:


二、multipart/form-data

使用表單上傳文件時,必須指定表單的 enctype屬性值爲 multipart/form-data. 請求體被分割成多部分,每部分使用 --boundary分割開始,緊接着內容描述信息,最後是字段具體內容(文本或二進制);若是傳輸的是文件,還要包含文件名和文件類型信息;
2.一、前端請求代碼

var reqParam = new FormData(document.form2);
xhr.send(reqParam);複製代碼
2.二、服務端解析代碼
express 提供了兩種插件 formidablemultiparty 來處理數據類型爲 multipart/form-data 的狀況,如下咱們分別用兩個插件進行處理;
2.2.一、formidable 插件
(1)安裝插件

npm install formidable --save複製代碼
(2)服務端解析處理

app.post('/formData1', function (req, res) {   
    var form = new formidable.IncomingForm();    
    form.uploadDir = "upload/";    
    form.parse(req, function (err, fields, files) {        
      var obj = {};        
      Object.keys(fields).forEach(function (name) {  
          obj[name] = fields[name];       
      });        
      Object.keys(files).forEach(function (name) {            
          if (files[name] && files[name].name) {                
             obj[name] = files[name];                
             fs.renameSync(files[name].path, form.uploadDir + files[name].name);          
        }        
     });      
     res.send(obj);    
   });
});複製代碼
2.2.二、multiparty 插件
(1)安裝插件

npm install multiparty--save複製代碼
(2)服務端解析處理
app.post('/formData2', function (req, res) {   
 // 解析一個文件上傳    
var form = new multiparty.Form();    
//設置編輯    
form.encoding = 'utf-8';    
//設置文件存儲路徑    
form.uploadDir = "upload/";   
 //設置單文件大小限制    
form.maxFilesSize = 2000 * 1024 * 1024;    
form.parse(req, function (err, fields, files) {        
     var obj = {};        
     Object.keys(fields).forEach(function (name) {            
          obj[name] = fields[name];       
     });       
     Object.keys(files).forEach(function (name) {            
         if (files[name] && files[name][0] && files[name][0].originalFilename) {               
             obj[name] = files[name];               
             fs.renameSync(files[name][0].path, form.uploadDir + files[name][0].originalFilename); 
         }       
      });        
      res.send(obj);    
    });
});複製代碼
2.三、瀏覽器請求 / 響應截圖
請求:


響應:


三、application/json

application/json 這個 Content-Type 做爲響應頭,用來告訴服務端消息主體是序列化後的 JSON 字符串。因爲 JSON 規範的流行,除了低版本 IE 以外的各大瀏覽器都原生支持 JSON.stringify,服務端語言也都有處理 JSON 的函數,使用 JSON 不會趕上什麼麻煩。
3.一、前端請求代碼

var reqParam = {   
     name: 'jack'
};
xhr.setRequestHeader('Content-type', 'application/json');
xhr.send(JSON.stringify(reqParam));複製代碼

3.二、服務端解析代碼前端

app.post('/applicationJson', bodyParser.json(), function (req, res) {    
var result = {        
    name: req.body.name,       
    sex: '男',        
    age: 15    
  };    
   res.send(result);
});複製代碼
3.三、瀏覽器請求 / 響應截圖
請求:


響應:


四、text/xml

它是一種使用 HTTP 做爲傳輸協議, XML 做爲編碼方式的遠程調用規範,它的使用也很普遍,能很好的支持已有的 XML-RPC 服務。不過, XML 結構仍是過於臃腫,通常場景用 JSON 會更靈活方便。
4.一、前端請求代碼

var text = '<?xml version="1.0"?><methodCall><methodName>examples.getStateName</methodName>' +    '<params><param><value><i4>41</i4></value></param></params></methodCall>';
xhr.setRequestHeader('Content-type', 'text/xml');
xhr.send(text);複製代碼
4.二、服務端解析代碼

app.post('/textXml',  bodyParser.urlencoded({extend:true}), function (req, res) {    
   var result = ''; 
   req.on('data', function (chunk) {       
    result += chunk;   
   });    
   req.on('end', function () {        
   res.send(result);   
   });
});複製代碼
4.三、瀏覽器請求 / 響應截圖
請求:


響應:


3、踩坑彙總

一、對於跨域請求,當 contentType改成 application/json,將觸發瀏覽器發送一個預檢 OPTIONS請求到服務器,再發送正常的 post 請求;
二、使用 new FormData(),而後設置 Content-type application/x-www-form-urlencoded 或者 multipart/form-data 會致使後端沒法正常解析,解決方法:就是不進行頭部設置, Content-type 會默認 爲 multipart/form-data,服務端正常解析;
三、 contentType 設置爲 application/x-www-form-urlencoded 時,傳給後端的請求參數爲 JSON字符串, chrome 調試框查看發送的請求參數多了冒號,以下所示:


這是由於 application/x-www-form-urlencoded 它將被解析成鍵值對展現,可是字符串進去是沒有改變的,可是展現的時候能看見。解決方法:若是爲 JSON字符串,則設置數據類型爲 application/json

4、總結

本文咱們主要介紹 Post 請求的 4 種 Content-Type 數據類型,以及如何使用 Express 來對每種 Content-Type 類型進行解析。已經將完整的代碼實例上傳到 githubgithub地址爲: github.com/fengshi123/… ,歡迎 stardemo 截圖以下所示:

相關文章
相關標籤/搜索