如何修复Multer中间件无法创建上传文件夹及修改文件名的问题?
解决Multer文件上传未生效的问题
核心问题总结
你的代码存在4个关键错误,直接导致Multer无法正常工作:
- 前端用JSON格式提交数据,而非
FormData,文件二进制根本没传到后端 - 前端文件DOM选择器ID写错(文件input的ID是
pdf,代码里写了myfile) - 后端Multer配置里的日志引用了未定义变量
- 上传目录未提前创建,Multer不会自动生成不存在的文件夹
分步修复代码
1. 修正前端EJS代码
必须用FormData包装表单数据(包括文件),不能用JSON提交:
<form enctype="multipart/form-data"> <input type="text" placeholder="Book Name" id="name" /> <input type="text" placeholder="Author " id="author" /> <input type="text" placeholder="Buy link" id="link" /> <input type="text" placeholder="Book description" id="desc" /> <input type="file" name="pdf" id="pdf" placeholder="upload file" /> <button type="submit">Add</button> </form> <script> let form = document.querySelector("form"); form.addEventListener("submit", async (e) => { e.preventDefault(); // 用FormData自动收集所有表单数据(含文件) const formData = new FormData(form); try { const res = await fetch("/addBooks", { method: "POST", body: formData // 直接传FormData,浏览器会自动设置正确的请求头 }); const result = await res.json(); console.log(result); } catch (err) { console.error(err); } }); </script>
修正说明:
- 替换JSON提交为
FormData,确保文件二进制数据能被后端接收 - 移除手动设置的
Content-Type,浏览器会为FormData自动配置multipart/form-data头 - 修复文件选择器ID错误(从
myfile改为pdf)
2. 修正后端Multer中间件代码
const multer = require('multer'); const fs = require('fs'); const path = require('path'); // 提前创建upload目录,不存在则自动生成 const uploadDir = path.join(__dirname, 'upload'); if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir, { recursive: true }); } const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, 'upload'); }, filename: function (req, file, cb) { const newFilename = `${Date.now()}-${file.originalname}`; cb(null, newFilename); // 修正日志变量,输出实际保存路径和文件名 console.log('保存路径:', 'upload', '文件名:', newFilename); }, }); const upload = multer({ storage }); route.post("/addBooks", upload.single("pdf"), addBook);
修正说明:
- 添加目录检测与创建逻辑,确保
upload文件夹存在 - 修复日志中未定义变量的错误,改用实际生成的文件名
- 补充
multer的引入语句(原代码遗漏)
3. 修正处理函数代码
文件上传后,文件信息存在req.file中,文本字段在req.body中,需从req.file.filename获取重命名后的文件名:
let addBook = async (req, res) => { console.log("文本字段 >> ", req.body); console.log("文件信息 >> ", req.file); // 校验是否有文件上传 if (!req.file) { return res.status(400).send({ msg: "请上传PDF文件" }); } let { bookName, bookAuthor, bookDesc, bookLink } = req.body; // 从Multer处理后的文件对象中获取最终文件名 let pdfFilename = req.file.filename; try { let _book = await books.create({ name: bookName, author: bookAuthor, description: bookDesc, buyLink: bookLink, pdf: pdfFilename }); res.status(200).send({ msg: "success" }); } catch (error) { console.error("系统错误:", error); res.status(400).send({ msg: "Wrong" }); } };
修正说明:
- 从
req.file.filename获取重命名后的文件名,而非前端传的原文件名 - 添加文件上传校验,避免空文件提交
- 完善错误日志,输出具体错误信息便于排查
验证步骤
- 启动后端服务,确认
upload目录已自动生成 - 前端选择PDF文件并提交表单
- 检查
upload目录下是否出现带时间戳的PDF文件 - 验证数据库是否正确保存了重命名后的文件名
内容的提问来源于stack exchange,提问作者tamer mansor
相关产品推荐
相关产品推荐

