在Heroku部署Express PERN应用时图片上传出现500错误如何解决
Heroku PERN应用图片上传返回500错误的解决方案
错误核心原因
- Heroku的dyno实例采用临时文件系统,仅支持运行期间的临时写入,所有写入本地的文件会在dyno重启、重新部署、实例伸缩时被清空。且你当前代码没有提前判断上传目录是否存在,路径不存在时直接调用
image.mv会直接触发错误返回500。 - 代码中使用的
../../build/uploads/img/为相对路径,Heroku Node.js运行环境的工作目录和本地开发环境不一致,相对路径解析后大概率指向不存在的目录,直接写入会抛出错误。
修复方案
生产环境标准方案
不要将用户上传的图片存储在Heroku本地,替换为第三方对象存储服务,上传逻辑改为将文件上传到对象存储后返回对应的公网访问地址,彻底规避Heroku临时文件系统的限制。
临时调试兼容方案
修改路径为绝对路径,服务启动时提前创建上传目录,修改后的代码如下:
const path = require('path'); const fs = require('fs'); // 拼接上传目录的绝对路径,__dirname为当前文件所在目录 const UPLOAD_DIR = path.resolve(__dirname, 'build', 'uploads', 'img'); // 启动时判断目录是否存在,不存在则递归创建 if (!fs.existsSync(UPLOAD_DIR)) { fs.mkdirSync(UPLOAD_DIR, { recursive: true }); } Router.post('/upload-image', (req, res) => { try { // 验证是否上传了图片 if (req.files === null) { return res.status(201).json({ statusRequest: 'ok', imagePath: '/uploads/img/avatar.png' }); } const image = req.files.file; const targetPath = path.join(UPLOAD_DIR, image.name); image.mv(targetPath, error => { if (error) { // 开发环境可打印错误排查,生产环境可移除 console.error('上传失败:', error); return res.status(500).json({ statusRequest: 'failed', errorInfo: 'Hubo un problema. Vuelve a intentarlo.' }); } return res.status(201).json({ statusRequest: 'ok', imagePath: `/uploads/img/${image.name}` }); }); } catch (error) { // 开发环境可打印错误排查,生产环境可移除 console.error('接口异常:', error); return res.status(400).json({ statusRequest: 'failed', errorInfo: 'Hubo un problema. Vuelve a intentarlo.' }); } });
注意:临时调试方案仅可用于测试,Heroku的dyno每24小时至少会自动重启一次,重启后所有上传的文件都会丢失,不可用于生产环境。
内容的提问来源于stack exchange,提问作者Chemuelon
相关产品推荐
相关产品推荐

