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

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

POST数据编码格式

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

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


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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容