图片上传(Node + Express)
在 Express 中处理文件上传,最常见的方案是使用 multer 中间件。它基于 busboy 实现,支持内存存储与磁盘存储,并允许自定义过滤逻辑。
来源整理自:vue3js.cn 面试官系列
multer 中间件
const multer = require('multer');
const path = require('node:path');
// 创建文件保存位置及文件保存后缀名
const multerStorage = multer.diskStorage({
// 缓存位置
destination: (req, file, cb) => {
cb(null, 'public/img/users'); // err, 路径名
},
filename: (req, file, cb) => {
const ext = file.mimetype.split('/')[1];
cb(null, `user-${req.user.id}-${Date.now()}.${ext}`);
},
});
// 过滤器:判断是否允许上传。可以在这里检测上传的文件是否是图片
const multerFilter = (req, file, cb) => {
if (file.mimetype.startsWith('image')) {
cb(null, true);
} else {
cb(new Error('Not an image!'), false);
}
};
const upload = multer({
storage: multerStorage,
fileFilter: multerFilter,
// dest: 'public/img/users', // 文件保存的位置
});
// 上传图片中间件:单文件字段 photo
exports.uploadUserPhoto = upload.single('photo');
补充
补充:完整的上传链路示例(路由 + 中间件 + 静态资源)。
// routes/userRoutes.js
const express = require('express');
const { uploadUserPhoto } = require('../middlewares/upload');
const router = express.Router();
router.patch('/updateMe',
uploadUserPhoto, // 解析 multipart/form-data
(req, res, next) => { // 写入数据库前可对图片做 resize / 压缩
if (!req.file) return next();
req.body.photo = req.file.filename;
next();
},
userController.updateMe,
);
// app.js 中需要把 uploads 目录暴露为静态资源
app.use('/img/users', express.static(path.join(__dirname, 'public/img/users')));
实战要点:
- 一定要在
multer之前先挂cookieParser、protect之类的鉴权中间件,否则无法在req.user上拿到 id 用于生成文件名。 - 大文件上传建议走对象存储(OSS/S3),前端直传后再把
key写入数据库,可极大降低服务器带宽。 - 生产环境务必设置
limits: { fileSize: 5 * 1024 * 1024 }等上限,避免被大文件拖垮。



