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

Express+EJS项目图片无法渲染问题求助

EJS页面外部图片无法加载的解决方案

问题说明

练习EJS项目时,页面其他内容正常渲染,但图片无法显示。尝试从Express Session获取图片链接、直接使用图片URL均无效;生成的HTML源码中图片URL单独访问正常,但通过应用服务加载时无法渲染。

相关代码

app.js 文件

//Imports
const path = require("path");
require("dotenv").config();
const express = require('express');
const morgan = require('morgan');
const helmet = require('helmet');
const partials = require('express-partials');
const app = express();
const session = require('express-session');
const passport = require('./config/passport.js');

//Variables
const PORT = 3000;
const EXPRESS_SESSION_SECRET = process.env.EXPRESS_SESSION_SECRET;

//Remove after development to minimize unnecessary realtime logs on server
app.use(morgan('tiny'));

//Express setup
app.use(express.json());
app.use(helmet());
app.disable('x-powered-by');

//Express page setup
app.set('views', path.join(__dirname + '/views'));
app.set('view engine', 'ejs');
app.use(partials());
app.use(express.static(path.join(__dirname + '/public')));

//Express session set up to be used on all routes
app.use(
  session({
    secret: EXPRESS_SESSION_SECRET,
    resave: false,
    saveUninitialized: false,
    cookie: { maxAge: 1000 * 60 *60 * 24 }
  })
);

//Initializes passport to be used on all routes
app.use(passport.initialize());
app.use(passport.session());


//Mounts the page router
const pageRouter = require('./routers/page-router.js');
app.use('/', pageRouter);

//Mounts the api router
const apiRouter = require('./routers/api-router.js');
app.use('/api', apiRouter);

//Starts server
app.listen(PORT, () => console.log(`Listening on ${PORT}`));

page-router.js 中/account的GET路由

//Imports necessary modules
const express = require('express');
const {ensureAuthenticated} = require('../middleware/auth-middleware.js');

//Creates the router
const pageRouter = express.Router();

//This page is protected and requires github authentication
pageRouter.get('/account', ensureAuthenticated, (req, res) => {
    res.render('account', { user: req.user });
});

//Exports the router
module.exports = pageRouter;

views/account.ejs 视图文件

<div class="row">
  <div class="six columns">
    <h1><%= user.username %></h1>
    <p>ID: <%= user.id %></p>
    <p>Name: <%= user.displayName %></p>
    <p>Bio: <%= user._json.bio %></p>
    <p>GitHub: <a href="<%= user._json.html_url %>">Link</a></p>
  </div>

  <div class="six columns">
    <img src="<%= user.photos[0].value %>" alt="Avatar">
  </div>
</div>

生成的HTML源码

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Codecademy OAuth Project</title>

        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link href="//fonts.googleapis.com/css?family=Raleway:400,300,600" rel="stylesheet" type="text/css">
        <link rel="stylesheet" href="css/normalize.css">
        <link rel="stylesheet" href="css/skeleton.css">
        <link rel="stylesheet" href="css/style.css">
    </head>
    <body>
        <div class="container">

            <nav>
                
                    <div>
                        <a href="/">Home</a> | 
                        <a href="/account">Account</a> | 
                        <a href="/logout">Log Out</a>
                    </div>
                
                </nav>
        <div class="row">
  <div class="six columns">
    <h1>brendengerber</h1>
    <p>Name: </p>
    <p>Bio: </p>
    <p>GitHub: <a href="https://github.com/brendengerber">Link</a></p>
  </div>

  <div class="six columns">
    <img src="https://avatars.githubusercontent.com/u/10082638?v=4" alt="Avatar">
  </div>
</div>
        </div>
    </body>
</html>

问题原因及解决方法

原因

项目中使用了helmet中间件,它默认会启用内容安全策略(CSP),限制页面只能加载同域资源。而头像图片来自外部域名(https://avatars.githubusercontent.com),因此被浏览器阻止加载。

解决步骤

  1. 验证问题:打开浏览器开发者工具(F12),查看控制台的报错信息,会看到CSP相关的拦截提示。
  2. 调整helmet配置:修改app.js中的helmet调用,添加允许加载外部图片及其他必要资源的规则:
//Express setup
app.use(express.json());
// 修改helmet配置,放开资源加载权限
app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      imgSrc: ["'self'", "https://avatars.githubusercontent.com"],
      styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"],
      fontSrc: ["'self'", "https://fonts.gstatic.com"]
    }
  }
}));
app.disable('x-powered-by');
  1. 开发阶段临时验证:如果只是开发测试,可以临时关闭CSP来快速确认问题:
app.use(helmet({ contentSecurityPolicy: false }));

修改后重启服务,即可正常加载外部头像图片。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 03:17:08