在Vercel的Express.js服务器上使用Multer存储图片失败问题排查
问题排查与解决方案
核心原因分析
Vercel无服务器环境的临时存储限制
Vercel的Node.js函数运行在临时容器中,容器的本地磁盘是短暂且非持久化的。Multer的diskStorage将文件写入本地uploads目录后,容器在函数执行完毕就会被销毁,文件也会被清理——日志显示“已处理”只是函数执行时临时写入了,后续马上被删除,自然无法通过静态路径访问。vercel.json路由配置无效
当前路由规则{"src": "uploads/(.*)", "dest": "uploads/$1"}试图指向本地uploads目录,但Vercel部署时:
- 若本地
uploads目录为空,Git不会跟踪空目录,部署后该目录不存在; - 即使目录存在,动态上传的文件也不会被持久化,所以这个路由本质无法访问到上传的文件。
- Express静态服务适配问题
app.use('/uploads', express.static('uploads'))在本地开发时有效,但在Vercel环境中,uploads目录的文件无法持久保存,静态服务自然找不到文件。
具体解决方案
1. 替换磁盘存储为持久化云存储(推荐)
放弃Multer的diskStorage,改用Vercel官方的Vercel Blob或第三方云存储(如Cloudinary、AWS S3)来存储上传的图片,步骤如下:
- 安装Vercel Blob SDK:
npm install @vercel/blob - 修改Multer配置为内存存储,接收文件后上传到Vercel Blob:
import { put } from '@vercel/blob'; import multer from 'multer'; // 改用内存存储 const storage = multer.memoryStorage(); const upload = multer({ storage }); // 在上传接口中处理文件 router.post('/create-jwt-object', upload.array('images', 2), async (req, res) => { if (!req.files) { return res.status(400).send('No files uploaded'); } const uploadedUrls = []; for (const file of req.files as Express.Multer.File[]) { const { url } = await put(file.originalname, file.buffer, { access: 'public', }); uploadedUrls.push(url); } // 后续使用uploadedUrls中的地址生成Google Wallet会员卡 res.status(200).json({ imageUrls: uploadedUrls }); });
2. 修正vercel.json配置(配合云存储)
如果使用云存储,无需再配置本地uploads的路由,保持后端路由即可:
{ "version": 2, "builds": [ {"src": "src/app.ts", "use": "@vercel/node"} ], "routes": [ {"src": "/(.*)", "dest": "src/app.ts"} ] }
3. 临时测试方案(不推荐生产环境)
如果只是临时测试,可修改Multer的存储路径为Vercel允许的临时目录(/tmp),并调整Express静态服务指向该目录,但文件仍会在容器销毁后丢失:
// 修改Multer存储路径 const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, '/tmp/uploads'); // Vercel允许的临时目录 }, filename: function (req, file, cb) { cb(null, file.originalname); } }); // 调整静态服务 app.use('/uploads', express.static('/tmp/uploads'));
内容的提问来源于stack exchange,提问作者Ilias Kadyrkulov
相关产品推荐
相关产品推荐

