POST三种常见的数据格式及NodeJS后台解析

前言:我们知道,服务端通常是根据请求头(headers)里面的 Content-Type 字段来判断请求中的消息主体是用何种方式进行编码的,然后再对主体进行解析。所以我们需要先了解一下POST的数据编码格式。
POST数据编码格式 POST的数据编码格式由Content-Type决定,而Content-Type有多种值,每个值都代表不同的数据格式
【POST三种常见的数据格式及NodeJS后台解析】1、常见的媒体格式类型:

  • text/html : HTML格式
  • text/plain :纯文本格式
  • text/xml : XML格式
  • image/gif :gif图片格式
  • image/jpeg :jpg图片格式
  • image/png:png图片格式
2、以applicaton开头的媒体类型:
  • application/json : JSON数据格式
  • application/xhtml+xml :XHTML格式
  • application/xml : XML数据格式
  • application/atom+xml :Atom XML聚合格式
  • application/pdf :pdf格式
  • application/javascript :js格式
  • application/msword : Word文档格式
  • application/octet-stream : 二进制流数据(如常见的文件下载)
  • application/x-www-form-urlencoded :form表单默认的数据格式类型,form表单数据被编码为key/value格式发送到服务器。
另外一种常见的媒体格式是上传文件之时使用的:
multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式。
其中POST提交可能用到的Content-Type类型如下:
  • multipart/form-data
  • application/x-www-form-urlencoded
  • text/xml
  • application/javascript
  • application/json
  • text/html
  • text/plain
在此我们会讨论其中常见的三种数据格式及其后台解析操作,为了方便测试,我们采用ApiPost(也可以使用PostMan)接口调试软件发起POST请求,后台则用NodeJS+Express搭配服务器。
后台解析请求主体的数据可能需要安装的模块,body-parser,multiparty;
其中,body-parser可用于express对请求进行分析,根据req.body字段便可以获得请求的主体。由于body-parser与Express分离了,所以需要自己重新安装该模块
安装命令:npm install body-parser
multiparty可用于接收提交的文件和解析form-data编码的数据
安装命令:npm install multiparty
// 引入模块 var express = require('express'); var path = require('path'); var ejs = require('ejs'); var app = express(); //var bodyParser=require('body-parser'); // app.use(bodyParser.json()); // app.use(bodyParser.urlencoded({ extended: false })); // 数据post接口路由 app.post('/action/:module', function (req, res) { var c_path = req.params.module; var Action = require('./action/' + c_path); Action.execute(req, res); }); // 设置views路径和模板 app.set('views', __dirname); app.set('view engine', 'html'); app.engine('html', ejs.__express); app.use('/', express.static(__dirname)); // 启动一个服务,监听从8080端口进入的所有连接请求 var server = app.listen(8888, function(){ var host = server.address().address; var port = server.address().port; console.log('Listening at http://%s:%s', host, port); });

PS:这里我的测试接口为http://localhost:8888/action/postTry,该接口会将POST请求里面的请求主体返回,这样我们可以看到POST的 数据在不同编码格式中是如何进行编码的
一、application/x-www-form-urlencoded
主要用于如下:
1.1、最常见的POST提交数据方式。
1.2、原生form默认的提交方式(可以使用enctype指定提交数据类型)。
1.3、jquery,zepto等默认post请求提交的方式
application/x-www-form-urlencoded 是最常用的一种请求编码方式,支持GET/POST等方法,所有数据变成键值对的形式 key1=value1&key2=value2
的形式,并且特殊字符需要转义成utf-8编号,如空格会变成 %20;
开始测试:
发送请求 用ApiPost发送请求,选择编码格式为application/x-www-form-urlencoded,我们输入字段name和value作为传送的参数,分别取值为111111和22222,在ApiPost可以查看返回的数据

POST三种常见的数据格式及NodeJS后台解析
文章图片
application/x-www-form-urlencoded.png 解析数据 由图片结果,我们可以看到我们发送的请求主体里面的数据为以下结果
name=111111&value=https://www.it610.com/article/22222

这与我们上述所述一致,现在我们需要在NodeJS里面进行解析,得到数据。以下为服务端解析代码
//导入querystring模块(解析post请求数据) var querystring = require('querystring'); exports.execute = function (req, res) { //console.log(req.body) /*如果使用了body-parser,则可以使用使用req.body获取到请求主体, 但是下方的req.on事件就会失去作用,因为此时数据以及接收完毕,所以没有办法触发处理事件*/ //面对post提交,nodejs用监听的写法处理 //data是一个事件,表示一个小包传输完毕后做的事情 var result = ""; req.on("data", function (chunk) { //console.log("小包传输完毕"); result += chunk; }); //end也是一个事件,表示所有的包传输完毕 req.on("end", function () { //所有的包传输完毕 result = decodeURI(result); // 前端提交中文数据时会进行url编码,所以先进行译码 var resultObject = querystring.parse(result); //对数据进行解析 //var result = JSON.parse(result); //console.log(resultObject); console.log(resultObject)//打印解析结果 message['status'] = 200; message['msg'] = '提交成功'; res.send(result) }); };

由于x-www-form-urlencoded是类似于url编码的一种编码方式,所以我们可以利用NodeJS内置的querystring模块进行解析,打印的解析结果如下:
[Object: null prototype] { name: '111111', value: '22222' }

这时候我们已经成功将请求主体由字符串解析为对象,可以通过访问对象属性的方式进行数据的访问。
二、multipart/form-data
使用表单上传文件时,必须指定表单的 enctype属性值为 multipart/form-data. 请求体被分割成多部分,每部分使用 --boundary分割;
开始测试:
发送请求 用ApiPost发送请求,选择编码格式为multipart/form-data,我们输入字段name和value作为传送的参数,分别取值为111111和22222,在ApiPost可以查看返回的数据

POST三种常见的数据格式及NodeJS后台解析
文章图片
multipart/form-data.png 解析数据 由图片结果,我们可以看到我们发送的请求主体里面的数据为以下结果
------WebKitFormBoundaryeDD6NSO9tLOAABh5 Content-Disposition: form-data; name="name"111111 ------WebKitFormBoundaryeDD6NSO9tLOAABh5 Content-Disposition: form-data; name="value"22222 ------WebKitFormBoundaryeDD6NSO9tLOAABh5--

由于NodeJS无法使用querystring直接将以上请求主体直接解析为对象,另外,上述提到的body-parser也不支持解析form-data编码的数据,此时的req.body={},这时候我们可以使用multiparty模块来进行数据的解析,具体可查看以下代码
var multiparty = require('multiparty'); //生成multiparty对象,并配置文件上传目标路径 var form = new multiparty.Form({ uploadDir: 'images/images' }); form.parse(req, function(err, fields, files) { var message = {}; if (err) { message["Code"] = 1; message["Msg"] = err; } else { message['name'] = fields.name[0]; //可根据fields获取其他数据,name以及values message['value'] = fields.value[0]; } res.send(message); });

打印结果如下
{ name: '111111', value: '22222' }

三、application/json
实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。而且现在服务端基本都可以处理JSON数据,所以不会出现什么大问题。
开始测试:
发送请求 用ApiPost发送请求,选择编码格式为application/json,我们输入字段name和value作为传送的参数,分别取值为111111和222222,在ApiPost可以查看返回的数据

POST三种常见的数据格式及NodeJS后台解析
文章图片
application/json.png 解析数据 由图片结果,我们可以看到我们发送的请求主体里面的数据为以下结果
{ "name": "111111", "value": "222222" }

此时的数据解析我们可以用JSON.parse对字符串进行解析获得对象
// res.send(req.body) //面对post提交,nodejs用监听的写法处理 //data是一个事件,表示一个小包传输完毕后做的事情 var result = ""; req.on("data", function (chunk) { //console.log("小包传输完毕"); result += chunk; }); //end也是一个事件,表示所有的包传输完毕 req.on("end", function () { //所有的包传输完毕 result = decodeURI(result); // 前端中文数据提交时会进行url编码,所以先进行译码 var resultObject = JSON.parse(result); console.log(resultObject) res.send(result) });

打印结果如下
{ name: '111111', value: '222222' }

另外,我们常用的axios HTTP工具库发起的axios post方法默认使用application/json格式编码数据,这个也可以说明在post请求中,使用这种编码格式应该是更加方便的。
个人觉得,在不需要进行文件上传的操作的时候,尽量还是选择application/json,因为在后台对数据的解析会变得比较简单,服务器基本都已经可以实现json数据的解析和封装了。

    推荐阅读