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 截图以下所示:

相关文章
相关标签/搜索