Express使用multer实现文件上传的示例代码
作者:云牧
环境搭建
首先,创建一个新的项目目录,并初始化 package.json 文件:
mkdir express-multer-test cd express-multer-test npm init -y
安装必要的包:
npm install express multer cors
express
:一个简洁而灵活的Node.js Web
应用框架。multer
:一个用于处理multipart/form-data
类型表单数据,特别适合于处理文件上传的中间件。cors
:提供跨域资源共享(CORS
)的中间件。
单文件上传
后端实现
在项目根目录下创建 index.js 文件,并添加以下内容:
const express = require('express') const multer = require('multer') const cors = require('cors') const app = express() // 使用 cors 中间件,允许所有来源的请求 app.use(cors()) // 配置 multer 中间件,设置文件存储的目录为 'uploads/' const upload = multer({ dest: 'uploads/' }) // 使用 multer 中间件处理单个文件上传 // 创建一个 POST 路由,路径为 '/aaa',文件字段名为 'aaa' app.post('/aaa', upload.single('aaa'), function (req, res, next) { console.log('req.file', req.file) console.log('req.body', req.body) }) app.listen(3333)
前端实现
新建一个 index.html,并通过 npx http-server 运行:
<!DOCTYPE html> <html lang="en"> <head> <script src="https://unpkg.com/axios@0.24.0/dist/axios.min.js"></script> </head> <body> <input id="fileInput" type="file" /> <script> const fileInput = document.querySelector('#fileInput') async function formData() { const data = new FormData() data.set('name', 'Yun') data.set('age', 20) data.set('aaa', fileInput.files[0]) const res = await axios.post('http://localhost:3333/aaa', data) console.log(res) } fileInput.onchange = formData </script> </body> </html>
通过 FormData + axios 上传文件
准备一张图片:
浏览器选中文件上传:
服务端打印的结果是:
fieldname 是前端上传过来的字段名
origialname 是图片的原始名称。
其余非文件字段在 req.body。
并且服务端多了 uploads 目录,里面就保存着我们上传的文件。
多文件上传
后端实现
在 index.js 中添加一个新的路由来处理多文件上传:
bbb 路由通过 array 方法来取上传的文件,并且指定最大数量的限制。
上传的文件通过 req.files 来取。
前端实现
<!DOCTYPE html> <html lang="en"> <head> <script src="https://unpkg.com/axios@0.24.0/dist/axios.min.js"></script> </head> <body> <!-- input 标签添加 multiple 属性允许多选 --> <input id="fileInput" type="file" multiple /> <script> const fileInput = document.querySelector('#fileInput') async function formData2() { const data = new FormData() data.set('name', 'Yun') data.set('age', 20) ;[...fileInput.files].forEach(item => { data.append('bbb', item) }) const res = await axios.post('http://localhost:3333/bbb', data) console.log(res) } fileInput.onchange = formData2 </script> </body> </html>
服务接收到了多个文件:
错误处理
在 express 里,约定有 4 个参数的中间件为错误处理中间件:
app.post('/bbb', upload.array('bbb', 2), (req, res, next) => { // ...之前的代码 }, (err, req, res, next) => { if (err instanceof MulterError && err.code === 'LIMIT_UNEXPECTED_FILE') { res.status(400).end('Too many files uploaded'); } });
不同字段上传
后端实现
如果需要处理多个字段上传文件,可以使用 fields 方法:
app.post( '/ccc', upload.fields([ { name: 'aaa', maxCount: 3 }, { name: 'bbb', maxCount: 2 }, ]), function (req, res, next) { console.log('req.files', req.files) console.log('req.body', req.body) } )
前端实现
async function formData3() { const data = new FormData() data.set('name', 'Yun') data.set('age', 20) data.append('aaa', fileInput.files[0]) data.append('aaa', fileInput.files[1]) data.append('bbb', fileInput.files[2]) data.append('bbb', fileInput.files[3]) const res = await axios.post('http://localhost:3333/ccc', data) console.log(res) }
上传后,服务器打印的信息:
不固定字段上传
后端实现
如果没有明确前端传过来的哪些字段是 file ,可以使用 any 接收:
app.post('/ddd', upload.any(), function (req, res, next) { console.log('req.files', req.files) console.log('req.body', req.body) })
前端实现
改下前端代码,这次设置 aaa、bbb、ccc、ddd 4 个 file 字段:
async function formData4() { const data = new FormData() data.set('name', 'Yun') data.set('age', 20) data.set('aaa', fileInput.files[0]) data.set('bbb', fileInput.files[1]) data.set('ccc', fileInput.files[2]) data.set('ddd', fileInput.files[3]) const res = await axios.post('http://localhost:3333/ddd', data) console.log(res) }
再次上传 4 个文件,可以看到服务端打印的消息:
只不过这时候不是 key、value 的形式了,需要自己遍历数组来查找。
文件名和存储目录自定义
之前通过 dest 指定了保存的目录:
现在重新指定:
const express = require('express') const multer = require('multer') const cors = require('cors') const fs = require('fs') const path = require('path') const app = express() app.use(cors()) // 磁盘存储 const storage = multer.diskStorage({ // 自定义目录 destination: function (req, file, cb) { try { // 尝试创建一个文件夹 fs.mkdirSync(path.join(process.cwd(), 'my-uploads')) } catch (e) {} cb(null, path.join(process.cwd(), 'my-uploads')) }, // 自定义文件名 filename: function (req, file, cb) { const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9) + '-' + file.originalname // 设置文件名为字段名+唯一后缀 cb(null, file.fieldname + '-' + uniqueSuffix) }, }) const upload = multer({ storage }) app.post('/ddd', upload.any(), function (req, res, next) { console.log('req.files', req.files) console.log('req.body', req.body) }) app.listen(3333)
file 对象没变:
浏览器再次上传,就可以看到目录和文件名都修改了:
到此这篇关于Express使用multer实现文件上传的示例代码的文章就介绍到这了,更多相关Express multer文件上传内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!