NodeJS集成Google Drive API获取图片失败,EJS报photos未定义
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}`); });
gallery.ejs 代码
<!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|
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

