nodejs

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

2019-10-06  本文已影响0人  TPKCJJ

前言:我们知道,服务端通常是根据请求头(headers)里面的 Content-Type 字段来判断请求中的消息主体是用何种方式进行编码的,然后再对主体进行解析。所以我们需要先了解一下POST的数据编码格式。

POST数据编码格式

POST的数据编码格式由Content-Type决定,而Content-Type有多种值,每个值都代表不同的数据格式

1、常见的媒体格式类型:

2、以applicaton开头的媒体类型:

另外一种常见的媒体格式是上传文件之时使用的:
multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式。

其中POST提交可能用到的Content-Type类型如下:

在此我们会讨论其中常见的三种数据格式及其后台解析操作,为了方便测试,我们采用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可以查看返回的数据


application/x-www-form-urlencoded.png
解析数据

由图片结果,我们可以看到我们发送的请求主体里面的数据为以下结果

name=111111&value=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可以查看返回的数据


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可以查看返回的数据


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数据的解析和封装了。

上一篇下一篇

猜你喜欢

热点阅读