浅谈Express.js解析Post数据类型的正确姿势

一、概念介绍

1、POST请求:HTTP/1.1 协议规定的 HTTP 请求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 这几种。其中 POST 一般用来向服务端提交数据。

2、 Content-Type是指 http/https 发送信息至服务器时的内容编码类型, Content-Type 用于表明发送数据流的类型,服务器根据编码类型使用特定的解析方式,获取数据流中的数据。四种常见的 POST 请求的 Content-Type 数据类型:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • application/json
  • text/xml

3、 Express.jsExpress 是一个保持最小规模的灵活的 Node.js Web 应用程序开发框架,为 Web 和移动应用程序提供一组强大的功能。

本文我们主要介绍 Post 请求的 4 种 Content-Type 数据类型,以及如何使用 Express 来对每种 Content-Type 类型进行解析。已经将完整的代码实例上传到 github,github 地址为: https://github.com/fengshi123/request_example,欢迎 star 。

二、四种POST请求的Content-Type数据类型解析

1、application/x-www-form-unlencoded

最常见的 POST 提交数据的方式,浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会默认以 application/x-www-form-urlencoded 方式提交数据。

1.1、前端请求代码

var reqParam = "name=jack";
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(reqParam);

1.2、服务端解析代码

app.post('/urlencoded', bodyParser.urlencoded({extend:true}), function (req, res) {
 var result = {
   name: req.body.name,
   sex: '男',
   age: 15
 };
 res.send(result);
});

1.3、浏览器请求 / 响应截图

请求:

响应:

2、multipart/form-data

使用表单上传文件时,必须指定表单的 enctype 属性值为 multipart/form-data . 请求体被分割成多部分,每部分使用 --boundary 分割开始,紧接着内容描述信息,最后是字段具体内容(文本或二进制);如果传输的是文件,还要包含文件名和文件类型信息;

2.1、前端请求代码

var reqParam = new FormData(document.form2);
xhr.send(reqParam);

2.2、服务端解析代码

express 提供了两种插件 formidablemultiparty 来处理数据类型为 multipart/form-data 的情况,以下我们分别用两个插件进行处理;

2.2.1、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.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.3、浏览器请求 / 响应截图

请求:

响应:

3、application/json

application/json 这个 Content-Type 作为响应头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify ,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。

3.1、前端请求代码

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

3.2、服务端解析代码

app.post('/applicationJson', bodyParser.json(), function (req, res) {
var result = {
  name: req.body.name,
  sex: '男',
  age: 15
 };
  res.send(result);
});

3.3、浏览器请求 / 响应截图

请求:

响应:

4、text/xml

它是一种使用 HTTP 作为传输协议, XML 作为编码方式的远程调用规范,它的使用也很广泛,能很好的支持已有的 XML-RPC 服务。不过, XML 结构还是过于臃肿,一般场景用 JSON 会更灵活方便。

4.1、前端请求代码

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.2、服务端解析代码

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、浏览器请求 / 响应截图

请求:

响应:

三、踩坑汇总

1、对于跨域请求,当 contentType 改为 application/json ,将触发浏览器发送一个预检 OPTIONS 请求到服务器,再发送正常的 post 请求;

2、使用 new FormData() ,然后设置 Content-typeapplication/x-www-form-urlencoded 或者 multipart/form-data 会导致后端无法正常解析,解决方法:就是不进行头部设置, Content-type 会默认 为 multipart/form-data ,服务端正常解析;

3、 contentType 设置为 application/x-www-form-urlencoded 时,传给后端的请求参数为 JSON 字符串, chrome 调试框查看发送的请求参数多了冒号,如下所示:

这是因为 application/x-www-form-urlencoded 它将被解析成键值对展示,但是字符串进去是没有改变的,但是展示的时候能看见。解决方法:如果为 JSON 字符串,则设置数据类型为 application/json

四、总结

本文我们主要介绍 Post 请求的 4 种 Content-Type 数据类型,以及如何使用 Express 来对每种 Content-Type 类型进行解析。已经将完整的代码实例上传到 githubgithub 地址为:https://github.com/fengshi123/request_example,欢迎 star demo 截图如下所示:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 基于node.js依赖express解析post请求四种数据格式

    node.js依赖express解析post请求四种数据格式 分别是这四种: www-form-urlencoded form-data application/json text/xml 1.www-form-urlencoded 这是http的post请求默认的数据格式,需要body-parser中间件的支持 服务器端的demo: var express = require('express'); var app = express(); var bodyParser = require('

  • 浅谈Express.js解析Post数据类型的正确姿势

    一.概念介绍 1.POST请求:HTTP/1.1 协议规定的 HTTP 请求方法有 OPTIONS.GET.HEAD.POST.PUT.DELETE.TRACE.CONNECT 这几种.其中 POST 一般用来向服务端提交数据. 2. Content-Type : 是指 http/https 发送信息至服务器时的内容编码类型, Content-Type 用于表明发送数据流的类型,服务器根据编码类型使用特定的解析方式,获取数据流中的数据.四种常见的 POST 请求的 Content-Type 数据

  • 浅谈Python xlwings 读取Excel文件的正确姿势

    使用Python加载最新的Excel读取类库xlwings可以说是Excel数据处理的利器,但使用起来还是有一些注意事项,否则高大上的Python会跑的比老旧的VBA还要慢. 这里我们对比一下,用几种不同的方法,从一个Excel表格中读取一万行数据,然后计算结果,看看他们的耗时. 1. 处理要求: 一个Excel表格中包含了3万条记录,其中B,C两个列记录了某些计算值,读取前一万行记录,将这两个列的差值进行计算,然后汇总得出差的和. 文件是这个样子:Book300s.xlsx . 2. 处理方式

  • 浅谈express.js框架中间件(middleware)

    _express.js_作为_Node.js_的老牌框架,是现有框架中最全面的.然而在学习express除了那些api之外,对于框架最重要的就是__中间件__这个概念了.如果理解了,就可以把这个框架玩活了,项目开发肯定会更加顺利,而且还可以开发很多额外的功能,甚至中间件扩展开发. 但是就这么一个东西,是很多学习node.js的小萌新们就算写出一个博客项目,都不知道它到底有啥作用.我当时在理解的时候也花了不少功夫,趁着没有啥工作,给各位学习express.js的一点点我的指导意见.当然,这里面可能

  • 浅谈Go中数字转换字符串的正确姿势

    在许多语言中,你可以轻松地将任何数据类型转换为字符串,只需将其与字符串连接,或者使用类型转换表达式即可.但是,如果你在Go中尝试执行似乎很明显的操作(例如将int转换为字符串),你不太可能获得预期的效果. 比如下面: string(120) 你期望返回的结果是什么?如果你有使用其他编程语言的经验,那么大多数人的猜测是" 123".相反,在Go中上面的类型转换会得到" E"之类的值,那根本不是我们想要的.因为string()会直接把字节或者数字转换为字符的UTF-8表

  • 浅谈使用 Yii2 AssetBundle 中 $publishOptions 的正确姿势

    本文介绍了使用 Yii2 AssetBundle 中 $publishOptions 的正确姿势,分享给大家,具体如下: 官方文档:http://www.yiiframework.com/doc-2.0/guide-structure-assets.html 有兴趣的同学可以先看下官方原文档 文档样例代码 <?php namespace app\assets; use yii\web\AssetBundle; class FontAwesomeAsset extends AssetBundle

  • 浅谈Java8对字符串连接的改进正确姿势

    我们提出一个需求:有一个 List<String>,将其格式化为 元素1, 元素2, 元素3, ... 元素N 的字符串形式. 毋庸置疑, Java8 之前我们的第一反应是使用 StringBuilder : public static String formatList(List<String> list, String delimiter) { StringBuilder result = new StringBuilder(); for (String str : list)

  • 浅谈node.js中间件有哪些类型

    概述 node中间件就是封装在程序中处理http请求的功能.node中间件是在管道中执行.中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯. 中间件为主要的逻辑业务所服务,可分为:应用级中间件.路由级中间件.内置中间件.第三方中间件.错误级中间件. 1.应用级中间件 每一个中间件就是调用一个函数,需要配合其他的中间件或者路由使用 server (函数) 拦截所有的路由 server.use('/reg',函数):拦截特定的路由 const express=require('ex

  • 浅谈Vue.js 1.x 和 2.x 实例的生命周期

    在Vue.js中,在实例化Vue之前,它们都是以HTML的文本形式存在文本编辑器中.当实例化后将经历创建.编译.销毁三个主要阶段. 以下是Vue.js 1.x 实例的生命周期图示: Vue.js 1.x 的生命周期钩子 1. init 在实例开始初始化时同步调用.此时数据观测.事件和Watcher都尚未初始化. 2. created 在实例化创建之后同步调用.此时实例已经结束解析选项,已建立:数据绑定.计算属性.方法.Watcher/事件回调,但是还没有开始DOM编译,$el还不存在. 3. b

  • 浅谈原生JS中的延迟脚本和异步脚本

    一.延迟脚本 defer HTML4.0中为<script> 标签添加了个defer属性.属性的用途是表民脚本在执行时不会影响页面的构造. 脚本会被延迟到页面加载完毕的时候,执行.也就是当浏览器解析到</html> 标签后才会执行代码.在HTML5规范中,defer属性中适用于外部脚本. 而家了defer  的脚本文件会比DOMContentLoaded事件触发前执行. 二.异步脚本 async HTML5为<script>添加了个async属性.这个属性与defer属

  • 浅谈vue.js导入css库(elementUi)的方法

    1.安装以下模块,让webpack可以解析css文件 cnpm install style-loader --save-dev cnpm install css-loader --save-dev cnpm install file-loader --save-dev 2.安装elementUi模块 cnpm install element-ui@next -S 3.在webpack.base.conf.js中添加配置 { test: /\\\\\\\\.css$/, loader: "styl

随机推荐