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

使用EJS模板渲染图片时Express服务器崩溃的问题排查

问题:Express+Mongoose+EJS项目中产品详情页图片加载触发CastError

我是Express JS、MongoDB新手,正在使用Mongoose ODM、ExpressJS和EJS模板引擎搭建简单在线购物应用。现有Product模型和根据动态路由获取产品详情的控制器,但在EJS模板中访问产品图片时遇错误。

Product模型

import { Schema, model } from 'mongoose';
const productSchema = new Schema({
    title: String,
    imgurl: String,
    price: Number,
    description: String,
    userID: {
        type: Schema.Types.ObjectId,
        ref: 'user',
    },
});

export const Product = model('Product', productSchema);

产品详情控制器

export function getProductDetails(req, res, next) {
    return Product.findById(req.params.id)
        .then(({ _doc }) => res.render('shop/details', { _doc }))
        .catch(console.log);
}

EJS模板

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Details</title>
    </head>
    <body>
        <h1><%= _doc.imgurl %></h1>
        <img src="<%= _doc.imgurl %>" alt="" />
    </body>
</html>

错误信息

CastError: Cast to ObjectId failed for value "fasdf" (type string) at path "_id" for model "Product"
{
  "messageFormat": undefined,
  "kind": "ObjectId",
  "value": "fasdf",
  "path": "_id",
  "reason": "BSONError: input must be a 24 character hex string, 12 byte Uint8Array, or an integer"
}

问题详情

在EJS模板的img标签src属性中使用_doc.imgurl时出现上述CastError,但在h1标签中使用该值无问题,期望服务器不崩溃并正确渲染页面。


解决方案

1. 调整路由顺序,避免静态资源被动态路由捕获

错误中的fasdf不是合法的MongoDB ObjectId,说明有请求将无效字符串当作产品ID传入了findById。大概率是静态资源路由和产品详情动态路由顺序颠倒,导致图片请求被动态路由拦截(比如请求/products/fasdf.jpg时,fasdf.jpg被当作ID传入)。

修复方法:将静态资源路由放在动态路由之前:

// 先挂载静态资源路由
app.use(express.static('public'));
// 再挂载产品详情动态路由
app.get('/products/:id', getProductDetails);

2. 完善控制器的错误处理与ID校验

当前控制器仅打印错误未做处理,会导致请求挂起或服务器崩溃。需要添加ID格式校验和错误响应:

import mongoose from 'mongoose';

export function getProductDetails(req, res, next) {
    // 先校验ID格式是否合法
    if (!mongoose.Types.ObjectId.isValid(req.params.id)) {
        return res.status(404).render('404', { message: '产品不存在' });
    }

    return Product.findById(req.params.id)
        .then((product) => {
            if (!product) {
                return res.status(404).render('404', { message: '产品不存在' });
            }
            // 直接传递product对象,EJS中调用更直观
            res.render('shop/details', { product });
        })
        .catch(err => {
            console.log(err);
            res.status(500).render('500', { message: '服务器错误' });
        });
}

3. 优化EJS模板的图片路径与变量调用

确保图片路径为静态资源目录下的绝对路径(比如/images/product.jpg),同时简化变量调用:

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Details</title>
    </head>
    <body>
        <h1><%= product.imgurl %></h1>
        <img src="<%= product.imgurl %>" alt="<%= product.title %>" />
    </body>
</html>

内容的提问来源于stack exchange,提问作者GOURAB MUKHERJEE

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 07:07:49