Vercel部署Express应用后图片上传API报Internal Server Error
问题:Express部署至Vercel后图片上传API返回“Internal Server Error”
已将Express应用部署到Vercel,其余API运行正常,但图片上传API返回“Internal Server Error”。本地运行该API完全正常,部署后出现问题:
- Postman中使用包含
name和file的form-data请求时报错 - 仅用binary方式上传文件可成功
相关代码
index.js中的上传API
app.post("/api/upload", upload.single("file"), async (req, res) => { res.status(200).json("File has been uploaded"); });
multer配置
const multerStorage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, "./images"); }, filename: (req, file, cb) => { cb(null, req.body.name); }, }); const upload = multer({ storage: multerStorage });
错误信息
Postman返回的错误
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Internal Server Error</pre> </body> </html>
Vercel错误日志
[POST] /api/upload 2022-12-14T15:52:55.912Z 0988f1fa-ba5c-49b8-ae08-889cc67e7889 ERROR Error: EROFS: read-only file system, open 'images/virtual.jpg'
解决方案
核心原因
Vercel的服务器文件系统是**只读(EROFS)**的,无法直接将文件写入本地目录(比如你配置的./images),这就是部署后报错的根本原因。本地环境有可写的文件系统,所以能正常运行。
修复步骤
- 改用multer的内存存储(
memoryStorage)代替磁盘存储,避免写入本地文件系统 - 将内存中的文件上传到第三方云存储服务(如Cloudinary、AWS S3、阿里云OSS等),Vercel不提供持久化的文件存储
修改后的代码示例
1. 切换到内存存储
const multer = require('multer'); // 使用内存存储,文件会暂存到内存中 const multerStorage = multer.memoryStorage(); const upload = multer({ storage: multerStorage });
2. 上传到云存储(以Cloudinary为例)
先安装Cloudinary依赖:
npm install cloudinary
然后修改上传API:
const cloudinary = require('cloudinary').v2; // 配置Cloudinary(从环境变量读取密钥,避免硬编码) cloudinary.config({ cloud_name: process.env.CLOUDINARY_CLOUD_NAME, api_key: process.env.CLOUDINARY_API_KEY, api_secret: process.env.CLOUDINARY_API_SECRET }); app.post("/api/upload", upload.single("file"), async (req, res) => { try { // 将内存中的文件上传到Cloudinary const result = await cloudinary.uploader.upload(req.file.path, { public_id: req.body.name // 使用传入的name作为文件名 }); // 返回云存储的文件地址 res.status(200).json({ message: "File has been uploaded", fileUrl: result.secure_url }); } catch (err) { res.status(500).json({ error: err.message }); } });
注意事项
- 在Vercel的项目设置中添加Cloudinary的环境变量(
CLOUDINARY_CLOUD_NAME、CLOUDINARY_API_KEY、CLOUDINARY_API_SECRET) - 其他云存储服务的集成逻辑类似,核心是避免写入Vercel的本地文件系统
内容的提问来源于stack exchange,提问作者Karan Sharma
相关产品推荐
相关产品推荐

