Node.js Web 框架 Express 接收表单数据和文件上传
在发送 HTTP 请求的时候,最常用的请求方式就是 GET 和 POST ,这里简单写一下 Express 获取 GET 和 POST 数据的方式。
GET 数据
GET 数据发送的时候会写在 URL 地址中,格式就是 name=value ,比如 page=1 ,多条数据之间用 & 分隔。
Express 获取 GET 数据的方式也比较简单,在路由处理函数中使用 req.query.name 就可以获取,其中 name 就是查询参数名称:
app.get('/get', (req, res) => {
const userName = req.query.userName;
const password = req.query.password;
res.json({userName, password});
});在获取 radio 单选框时也是用 req.query.name 获取,一般一组单选框的 name 都是一样的,通过单选框的 name 可以获取 value 。
获取 checkbox 复选框也可以用 name 获取,一组复选框的 name 一般都不一样,复选框选中可以通过 name 获取 value 。复选框没有选中的情况下 name 和 value 都不会出现在 URL 中,通过 res.query.name 获取的也是 undefined 。
POST 数据
获取 POST 数据需要使用 body-parser 中间件,下面使用 npm 安装 body-parser:
npm install body-parser --save在路由处理函数中可以通过 req.body.name 获取 POST 数据:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
// 注册 body-parser 解析 URL 数据
app.use(bodyParser.urlencoded({extended: false}));
// 注册 body-parser 解析 JSON 数据
app.use(bodyParser.json());
app.post('/post', (req, res) => {
const userName = req.body.userName;
const password = req.body.password;
res.send({userName, password});
});我在注册 body-parser 中间件的时候调用了 urlencoded 和 json ,其中 urlencoded 就是普通的 URL Query 数据,格式为 name=value&name=value ,header 的 Content-type 一般为 application/x-www-form-urlencoded 。
json 就是解析 JSON 数据,JSON 数据的 header 的 Content-type 是 application/json ,body-parser 会根据 Content-type 来判断数据类型。
获取 JSON 数据可以直接使用 req.body :
app.post('/post', (req, res) => {
const jsonData = req.body;
res.json(jsonData);
});JSON 数据直接就可以使用,不需要再调用 JSON.parse 来转换。
使用 req.body 获取的 JSON 数据和客户端的格式是一样的,客户端发送的数据如果是 {"userName" : "Mr. Ma", "password": "123"} ,req.body 获取的数据也是 {"userName" : "Mr. Ma", "password": "123"} 。
上传文件
处理上传文件需要使用 multer 中间件,下面使用 npm 安装 multer :
npm install [email protected] --save单文件
下面使用 multer 处理上传文件:
const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const app = express();
// 设置上传文件的存储位置
const upload = multer({dest: path.join(__dirname, 'upload')});
app.post('/upload', upload.single('imgFile'), (req, res) => {
// 获取文件信息
const fileInfo = req.file;
// 把文件重命名为原来的文件名
fs.renameSync(
fileInfo.path,
path.join(__dirname, 'upload', fileInfo.originalname)
);
res.send('上传完成');
});我上面设置的文件存储位置是 upload 目录,上传的文件默认会随机生成一个文件名,在文件上传完成后可以给文件重命名。我这里为了方便,使用了 fs.renameSync 来同步修改文件名。
在处理上传单文件请求时,第二个参数需要调用 multer 上传配置的 single ,single 的参数就是文件表单 name 。在路由处理函数中使用 req.file 可以获取文件信息,文件信息如下:
{
"fieldname": "imgFile",
"originalname": "test.gif",
"encoding": "7bit",
"mimetype": "image/gif",
"destination": "D:\\web\\express-test\\upload",
"filename": "d3ab37846b0179f51afc27ca32e79d76",
"path": "D:\\web\\express-test\\upload\\d3ab37846b0179f51afc27ca32e79d76",
"size": 109362
}属性说明:
fieldname:文件表单名称originalname:原来的文件名称encoding:编码mimetype:文件类型destination:文件存储位置filename:随机生成的文件名path:文件存储位置,包含随机生成的文件名size:文件大小(字节)
多文件
文件表单是可以多选的,下面处理多文件上传:
const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const app = express();
// 设置上传文件的存储位置
const upload = multer({dest: path.join(__dirname, 'upload')});
app.post('/upload', upload.array('imgFile'), (req, res) => {
const fileInfo = req.files;
// 把上传的文件重命名为原来的名称
fileInfo.forEach(file => {
fs.renameSync(
file.path,
path.join(__dirname, 'upload', file.originalname)
);
});
res.send(fileInfo.length + '个文件上传完成');
});处理多文件上传使用的是 multer 的 array ,参数还是表单 name ,在路由处理函数中可以使用 req.files 获取文件信息。
多文件的文件信息和单文件是一样的,只是多文件是一个数组。
多个不同 name 的文件字段
form 可以包含多个不同 name 的文件表单,FormData 也可以添加多个不同 name 的键值对。
下面处理一组不同 name 的文件上传:
// 设置上传文件的存储位置
const upload = multer({dest: path.join(__dirname, 'upload')});
// fields 配置
const fieldsConfig = [
{name: 'imgFile', maxCount: 1},
{name: 'textFile', maxCount: 1}
];
app.post('/upload', upload.fields(fieldsConfig), (req, res) => {
const fileInfo = req.files;
// 把 imgFile 字段的文件重命名为原来的名称
fileInfo.imgFile.forEach(file => {
fs.renameSync(
file.path,
path.join(__dirname, 'upload', file.originalname)
);
});
// 把 textFile 字段的文件重命名为原来的名称
fileInfo.textFile.forEach(file => {
fs.renameSync(
file.path,
path.join(__dirname, 'upload', file.originalname)
);
});
res.send('文件上传完成');
});使用 multer 的 fields 可以处理多个文件字段的文件上传,fields 的参数是一组 fields 配置,fields 配置的格式如下:
[
{name: 'imgFile', maxCount: 1},
{name: 'textFile', maxCount: 1}
]name 就是文件字段名称,maxCount 就是文件数量限制,超出限制的文件会无法上传。
在路由处理函数中可以使用 req.files.name 来获取指定字段的文件,获取的也是一个对象数组:
[
{
"fieldname": "textFile",
"originalname": "新建文本文档.txt",
"encoding": "7bit",
"mimetype": "text/plain",
"destination": "D:\\web\\express-test\\upload",
"filename": "cd0c8055d865a61dc582204a999bf210",
"path": "D:\\web\\express-test\\upload\\cd0c8055d865a61dc582204a999bf210",
"size": 5
}
]multer 配置
在初始化 multer 的时候可以传入一个对象来配置文件存储,下面是一个简单的配置:
const multer = require('multer');
const upload = multer({
// 存储位置
dest: path.join(__dirname, 'upload'),
limits: {
// 最大文件大小为 1MB
fileSize: 1024 * 1024,
// 最大字段数,默认不限制
fields: 2,
// 可以同时上传的最大文件数,默认不限制
files: 1
}
});下面是 limits 可以设置的上传限制:
fieldNameSize:设置上传字段名的最大长度,默认为 100 字节fieldSize:设置上传字段值的最大长度,默认为 Infinityfields:设置可以同时上传的最大字段数,默认为 InfinityfileSize:设置上传文件的最大大小(以字节为单位),默认为 Infinityfiles:设置可以同时上传的最大文件数,默认为 Infinityparts:设置上传字段和文件的最大总数,默认为 InfinityheaderPairs:设置请求头中键值对的最大数量,默认为 2000
multer 默认会随机生成文件名,你也可以通过设置 multer 存储引擎的方式来设置文件名:
const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
// multer 存储引擎配置
const storage = multer.diskStorage({
// 设置文件存储位置
destination: (req, file, cb) => {
cb(null, path.join(__dirname, 'upload'));
},
// 设置文件名
filename: (req, file, cb) => {
// 获取当前的时间戳
const timestamp = new Date().getTime();
// 把文件名设置为时间戳 + 原来的文件名
cb(null, timestamp + '-' + file.originalname);
}
});
// 初始化 multer
const upload = multer({ storage: storage });上面把文件名设置为 时间戳-原文件名 主要是为了避免出现同名的文件。
版权声明:本文为原创文章,版权归 Changbin's Blog 所有,转载请联系博主获得授权。
本文地址:https://www.misterma.com/archives/934/
如果对本文有什么问题或疑问都可以在评论区留言,我看到后会尽量解答。