Skip to content

ExpressJS - 文件上传处理

Express.js - 使用 Multer 处理文件上传

Section titled “Express.js - 使用 Multer 处理文件上传”

文件上传是 Web 应用程序中的常见功能,从个人资料图片到文档提交。在 Express.js 中,用于处理 multipart/form-data(主要用于文件上传)的标准库是 Multer。

Multer 是一个中间件,它会将 file 对象(用于单文件上传)或 files 对象(用于多文件上传)添加到 request 对象中。这些对象包含有关已上传文件的信息。

首先,使用 npm 安装 Multer。

# 安装 Multer
npm install multer

使用 Multer 最简单的方法是指定一个目标目录。Multer 会将上传的文件以随机生成的文件名保存到该目录中。

import express from 'express';
import multer from 'multer';
import path from 'path';
const app = express();
// 配置 Multer 将文件存储在 'uploads/' 目录中
const upload = multer({ dest: 'uploads/' });
// 创建处理单个文件上传的路由
// 字符串 'avatar' 必须与 HTML 表单中文件输入字段的 'name' 属性匹配。
app.post('/profile', upload.single('avatar'), (req, res, next) => {
// req.file 包含有关已上传文件的信息
console.log('File details:', req.file);
// req.body 将包含文本字段(如果有的话)
console.log('Body details:', req.body);
res.status(200).send('File uploaded successfully!');
});
app.listen(3000, () => console.log('Server started on port 3000'));

req.file 对象将如下所示:

{
fieldname: 'avatar',
originalname: 'profile-picture.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: 'uploads/',
filename: 'a1b2c3d4e5f6a1b2c3d4e5f6',
path: 'uploads/a1b2c3d4e5f6a1b2c3d4e5f6',
size: 12345
}

为了更精细地控制文件的存储位置和命名方式,请使用 multer.diskStorage。

const storage = multer.diskStorage({
destination: (req, file, cb) => {
// 上传文件的目标目录
cb(null, 'uploads/');
},
filename: (req, file, cb) => {
// 创建一个唯一文件名以避免覆盖
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
}
});
const uploadWithCustomStorage = multer({ storage: storage });
app.post('/photo', uploadWithCustomStorage.single('image'), (req, res) => {
res.send(`File uploaded and saved as ${req.file.filename}`);
});

验证上传至关重要,以确保用户只提交允许的文件类型和大小。您可以在 Multer 的选项中进行配置。

const uploadValidated = multer({
storage: storage, // 使用之前定义的自定义存储配置
limits: {
fileSize: 1024 * 1024 * 5 // 文件大小限制为 5MB
},
fileFilter: (req, file, cb) => {
// 只允许图片(jpeg, jpg, png)
const allowedTypes = /jpeg|jpg|png/;
const mimetype = allowedTypes.test(file.mimetype);
const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
if (mimetype && extname) {
return cb(null, true);
}
cb(new Error('Error: File upload only supports the following filetypes - ' + allowedTypes));
}
});
// 使用已验证的上传中间件的路由
app.post('/upload-image', uploadValidated.single('productImage'), (req, res) => {
res.json({ message: 'Image uploaded successfully!', file: req.file });
}, (error, req, res, next) => {
// Multer 错误的自定义错误处理程序
res.status(400).json({ error: error.message });
});

要在单个请求中上传多个文件,请使用 upload.array(fieldname, maxCount)。

// 这将接受字段名为 'gallery' 的最多 10 个文件
app.post('/gallery', uploadValidated.array('gallery', 10), (req, res) => {
// req.files 将是一个文件对象数组
console.log(req.files);
res.send(`${req.files.length} files uploaded successfully!`);
});

要测试您的上传端点,您可以使用 Postman 等 API 客户端。创建一个 POST 请求,选择 Body 选项卡,选择 form-data,然后将键的类型从 ‘Text’ 切换到 ‘File’ 以选择您的文件。键名必须与您在 Multer 配置中指定的字段名匹配(例如 ‘avatar’、‘image’、‘gallery’)。