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 multer@1.4.4 --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 });
上面把文件名设置为 时间戳-原文件名
主要是为了避免出现同名的文件。
版权声明:本文为原创文章,版权归 Mr. Ma's Blog 所有,转载请联系博主获得授权。
本文地址:https://www.misterma.com/archives/934/
如果对本文有什么问题或疑问都可以在评论区留言,我看到后会尽量解答。