前言
在 Node.js 中处理文件上传是一个常见的需求,比如用户上传头像或文档。
那么,如何简单、安全地接收并保存这些文件呢?
本文说说 multer
的库,它可以帮助我们快速实现这一功能。
小问题:为什么使用 multer
而不是 Node.js 原生模块来处理文件上传。
🤔 补充知识:原生模块如何实现文件上传?
使用 Node.js 原生模块实现文件上传需要手动解析 multipart/form-data 格式的请求体,处理数据流并识别边界符。
然后逐个字段提取文件内容和元数据,最后通过 fs 模块将文件缓冲区写入磁盘,整个过程需要处理复杂的字节级操作和错误边界情况。
总之,比较麻烦!!
正文
什么是 Multer?
Multer 是一个 Node.js 中间件,专门用于处理 multipart/form-data
类型的表单数据(即文件上传)。
它基于 busboy
构建,可以高效地解析传入的请求,并将文件保存到服务器指定目录,同时提供对上传文件的元数据(如文件名、大小、类型)的访问。
🤔 补充知识: multipart/form-data 是啥类型?
multipart/form-data
是一种用于在 HTTP 请求中传输二进制数据(如文件)和文本数据混合内容的编码类型,它通过特定的边界分隔符将表单中的不同字段和数据分割成多个部分,每个部分可以独立设置内容类型和编码,使其能够同时高效传输文本字段和文件等二进制数据。说人话,就是网页表单要同时上传"文字"和"文件"时用的格式。比如你填用户名(文字)又传头像(图片),浏览器就会把文字和图片打包成一个特殊包裹,里面用"分隔线"把不同内容隔开,服务器收到后知道哪里是文字、哪里是文件,分别处理。
Multer 用起来很简单:你只需配置文件存到哪、叫什么名,就能处理单个文件、多个文件甚至文字图片混传的情况,还能设置文件大小和类型限制,防止乱传文件。
基本用法
以下是一个基于 Express + js 的示例,演示如何使用 Multer 实现单文件上传:
-
安装 Multer
bashnpm install multer
-
创建 Express 服务并配置 Multer
javascript
const express = require('express')
const multer = require('multer')
const app = express()
/* 存储配置开始 */
// 配置磁盘存储,也就是文件上传到服务器的目录
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/') // 文件保存目录
},
filename: (req, file, cb) => {
// 自定义文件名:时间戳+原文件名
cb(null, Date.now() + '-' + file.originalname)
}
})
/* 存储配置结束 */
const upload = multer({storage})
/* 上传路由开始 */
// 处理单文件上传(字段名为 'avatar')
app.post('/upload', upload.single('avatar'), (req, res) => {
console.log(req.file) // 上传文件的信息
res.send('文件上传成功!')
})
/* 上传路由结束 */
/* 服务启动开始 */
app.listen(3000, () => {
console.log('服务运行在端口 3000')
})
/* 服务启动结束 */
-
运行测试
-
选
POST
方法 -
Body
选form-data
-
key 那边输入 avatar,因为代码中写的是 upload.single('avatar'),然后同样在 key 的那边选择"file",然后在 value 那边选择一个图片
-
点击发送,你会收到类似下面的结果,这就完成了 ✅️!!
json
{
"fieldname": "avatar",
"originalname": "fufu.jpg",
"encoding": "7bit",
"mimetype": "image/jpeg",
"destination": "uploads/",
"filename": "1760977045699-fufu.jpg",
"path": "uploads\\1760977045699-fufu.jpg",
"size": 340363
}
其他上传场景
-
多文件上传 :
javascriptapp.post('/photos', upload.array('photos', 5), (req, res) => { console.log(req.files) // 文件数组 })
-
混合字段(文本+文件) :
javascriptapp.post('/submit', upload.fields([{name: 'avatar'}, {name: 'gallery'}]), (req, res) => { console.log(req.files) // 文件分组信息 console.log(req.body) // 文本字段 })
最后
简单回顾下前言中的问题:
为什么选择 Multer 而不是 Node.js 原生模块?
因为原生模块(如 http
或 fs
)需要手动解析复杂的 multipart
请求体,处理文件流和边界符,代码冗长且易出错。
Multer 做好了封装,开发者直接用 Multer 就可以了,省心方便。