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

NodeJS集成Google Drive API获取图片失败,EJS报photos未定义

问题:NodeJS + Google Drive API 画廊页面无法获取图片,EJS报错photos is not defined

我正在用NodeJS开发画廊页面,目标是从公开的Google Drive文件夹拉取所有图片。已启用Google Drive API并完成与NodeJS应用的连接,但访问/gallery路径时,EJS无法获取图片并抛出错误。


Server.js 代码

const express = require('express');
const sendEmail = require('./public/JS/sendEmail');
const fs = require('fs');
const path = require('path');
const { google } = require('googleapis'); // 导入Google API客户端

const app = express();
const port = 3000;

app.use(express.static('public'));

app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
app.use(express.urlencoded({ extended: true }));

const routesDir = path.join(__dirname, 'routes');
fs.readdirSync(routesDir).forEach((file) => {
  if (file.endsWith('.js')) {
    const route = require(path.join(routesDir, file));
    app.use(`/${file.replace('.js', '')}`, route);
  }
});

app.get('/', (req, res) => {
  res.render('index', { data: 'Data here...' });
});

app.get('/gallery', async (req, res) => {
  try {
    // 创建Google Drive API客户端
    const drive = google.drive({ version: 'v3' });

    const folderId = '1agwyqLRDj4t_PsF9IOZfDdObrtJ3Ti7X';

    // 列出指定文件夹中的所有图片
    const response = await drive.files.list({
      q: `'root' in parents and (mimeType='image/jpeg' or mimeType='image/png' or mimeType='image/gif')`,
      fields: 'files(id, name, webViewLink)',
    });

    const photos = response.data.files;
    console.log(photos); // 没有打印出图片数据
    res.render('gallery', { photos }); // 渲染画廊页面并传入图片数据
  } catch (err) {
    console.error('从Google Drive获取图片出错:', err);
    res.status(500).send('Internal Server Error');
  }
});


// Nodemailer 邮件发送
app.post('/send', (req, res) => {
  sendEmail(req.body)
    .then((info) => {
      const currentURL = `${req.protocol}://${req.get('host')}`;
      res.redirect(`${currentURL}/contacts?success=true`);
    })
    .catch((err) => {
      const currentURL = `${req.protocol}://${req.get('host')}`;
      res.redirect(`${currentURL}/contacts?success=false`);
    });
});

app.listen(port, '0.0.0.0', () => {
  console.log(`Server running at port:${port}`);
});

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=Raleway:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
      rel="stylesheet"
    />
    <link rel="stylesheet" href="/styles/footer.css" />
    <link rel="stylesheet" href="/styles/global.css" />
    <link rel="stylesheet" href="/styles/responsive/nav.css" />
    <link rel="stylesheet" href="/styles/nav.css" />
    <link rel="stylesheet" href="/styles/responsive/footer.css" />
    <link rel="stylesheet" href="/styles/loadingScreen.css" />
    <link rel="stylesheet" href="/styles/gallery.css">
    <link rel="shortcut icon" href="/img/logo.png" />
    <title>Gallery</title>
</head>
<body>
    <%-include ('partials/loading-screen') %>
    <%-include ('partials/header') %>
    
<h1 class="main-heading">Gallery</h1>

<div class="photo-container">
    <% photos.forEach(photo => { %>
      <a href="<%= photo.webViewLink %>" target="_blank">
        <img src="<%= photo.webViewLink %>" alt="<%= photo.name %>" />
      </a>
    <% }) %>
  </div>

    

    <%-include ('partials/footer') %>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.1/gsap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.1/ScrollTrigger.min.js"></script>
    <script src="/JS/mobileMenu.js"></script>
    <script src="/JS/loadingAnimation.js"></script>
</body>
</html>

报错信息

ReferenceError: /Users/kristiyanlyubenov/Desktop/Welldoers/views/gallery.ejs:29
27|
28|

29| <% photos.forEach(photo => { %>
30|
31| <%= photo.name %>
32|

photos is not defined


问题原因及修复步骤

1. Google Drive API 客户端未授权

你创建了google.drive实例,但未传入授权凭据,导致API调用静默失败,photos变量为undefined,EJS渲染时触发未定义错误。

修复:
配置服务账号授权(需提前生成服务账号密钥文件),修改客户端创建代码:

// 加载服务账号密钥
const auth = new google.auth.GoogleAuth({
  keyFile: path.join(__dirname, 'service-account-key.json'), // 替换为你的密钥文件路径
  scopes: ['https://www.googleapis.com/auth/drive.readonly'],
});

// 创建带授权的Drive客户端
const drive = google.drive({ version: 'v3', auth });

2. 文件查询条件错误

你写的查询条件是'root' in parents,但目标是指定的文件夹(folderId: '1agwyqLRDj4t_PsF9IOZfDdObrtJ3Ti7X'),这会拉取Drive根目录的图片而非目标文件夹的内容。

修复:
修改查询条件为指定文件夹:

q: `'${folderId}' in parents and (mimeType='image/jpeg' or mimeType='image/png' or mimeType='image/gif')`,

3. 处理空数据场景

即使API调用成功,也可能返回空数组。修改EJS代码,先判断photos是否存在,避免报错:

<div class="photo-container">
    <% if (photos && photos.length > 0) { %>
        <% photos.forEach(photo => { %>
          <a href="<%= photo.webViewLink %>" target="_blank">
            <img src="<%= photo.webViewLink %>" alt="<%= photo.name %>" />
          </a>
        <% }) %>
    <% } else { %>
        <p>No photos found.</p>
    <% } %>
</div>

4. 检查路由冲突

你通过routesDir自动加载路由文件,如果routes目录下存在gallery.js,会覆盖你写的app.get('/gallery')路由,导致当前逻辑根本不执行。

修复:
删除routes目录下的gallery.js文件,或者将画廊逻辑迁移到该文件中,避免路由冲突。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 12:03:09