从MongoDB读路径加载Public文件夹图片遇Heroku 404问题求助
问题描述
我尝试将表单上传的图片加载到首页,已在app.js中正确映射Public文件夹,图片存储路径为/public/assets/img/filename.ext。本地和AWS C9环境测试正常,但部署到Heroku staging站点时,图片出现404错误(实际文件确实存在),寻求解决建议或代码修正方案。
博客文章Schema
// schema setup var mongoose = require("mongoose"); var postSchema = new mongoose.Schema({ title: String, image: String, uploadedImage: { data: Buffer, contentType: String, }, dest: String, postdata: String, excerpt: String, tag: String, icon: String, color: String, featured: String, keywords: String, description: String, slug: String, create: {type: Date, default: Date.now}, author: { id: { type: mongoose.Schema.Types.ObjectId, ref: "User" }, username: String }, }); module.exports = mongoose.model("Posts", postSchema);
表单提交路由
require("dotenv").config(); const express = require("express"), router = express.Router(), Posts = require("../models/blog"), upload = require("../middleware/upload"), path = require('path'), fs = require('fs'), middleware = require("../middleware"), slugify = require('slugify'); // CREATE router.post("/", middleware.isLoggedIn, middleware.isAdmin, upload.single('uploadedImage'), function(req,res){ var title = req.body.title; var image = req.body.image; var postdata = req.body.postdata; var exceprt = req.body.excerpt; var tag = req.body.tag; var icon = req.body.icon; var color = req.body.color; var featured = req.body.featured; var keywords = req.body.keywords; var description = req.body.description; var dest = req.file.filename; var slug = slugify(title); var uploadedImage = { data: fs.readFileSync(path.join('./public/assets/img/' + req.file.filename)), contentType: 'image/png' }; var author = { id: req.user._id, username: req.user.username }; // link dB to post values var newPost= {title:title, slug:slug, image:image, postdata:postdata, excerpt:exceprt, tag:tag, icon:icon, color:color, featured:featured, author:author, keywords:keywords, description:description, dest:dest, uploadedImage:uploadedImage}; Posts.create(newPost, function(err, newlyCreated) { if (err){ console.log(err); }else{ console.log("slug:" + slug); console.log(req.file.path); res.redirect("/blog"); } }); });
EJS图片调用代码
<% Posts.forEach(function(post){ %> <img src="/assets/img/<%= post.dest %>" class="img-fluid" /> <% }); %>
解决建议
1. 处理Heroku临时文件系统问题
Heroku的文件系统是临时存储,应用重启(部署、休眠唤醒等)后,所有上传的本地文件会被清空。这是核心问题:你看到的“文件存在”只是当前会话的临时状态,重启后就会丢失。
- 替代方案:改用云存储服务(如AWS S3、Cloudinary)存储上传的图片,将图片URL存入数据库,而非本地文件路径。
2. 修复路径解析问题
- 将相对路径改为绝对路径,避免Heroku环境下路径解析错误:
把path.join('./public/assets/img/' + req.file.filename)改为path.join(__dirname, '../public/assets/img', req.file.filename) - 检查
upload中间件的存储配置,确保文件确实被写入到指定的public/assets/img目录。
3. 验证静态资源映射
确认app.js中的静态资源映射使用绝对路径:
app.use(express.static(path.join(__dirname, 'public')));
4. 移除不必要的数据库Buffer存储
当前代码将图片二进制数据存入uploadedImage.data,会增大数据库体积且无意义。既然已存储文件路径,可删除uploadedImage相关字段及存储逻辑,优化性能。
5. 云存储快速适配示例(以Cloudinary为例)
- 安装依赖:
npm install cloudinary multer-storage-cloudinary - 配置Cloudinary存储中间件,替换本地上传逻辑
- 将Cloudinary返回的图片URL存入Post的
image字段,EJS直接调用该URL即可
内容的提问来源于stack exchange,提问作者Andrew Buccellato
相关产品推荐
相关产品推荐

