You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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),这就是部署后报错的根本原因。本地环境有可写的文件系统,所以能正常运行。

修复步骤

  1. 改用multer的内存存储(memoryStorage)代替磁盘存储,避免写入本地文件系统
  2. 将内存中的文件上传到第三方云存储服务(如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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 01:40:28