Google Drive API problem connecting with NodeJS

73 Views Asked by At

I am trying to create a gallery page in my NodeJS app. However, there it seems like something isn't working with the connection. The idea is to get all photos from a Google Drive folder that is public. I enabled Google Drive API and connected it with the NodeJS app. Despite all that, if I go to /gallery where the images should be displayed ejs doesn't get any images and throws an error. I include the server.js code and the gallery.ejs code:

Server.js

const express = require('express');
const sendEmail = require('./public/JS/sendEmail');
const fs = require('fs');
const path = require('path');
const { google } = require('googleapis'); // Add this line to import Google API client

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 {
    // Create a Google Drive API client
    const drive = google.drive({ version: 'v3' });

    const folderId = '1agwyqLRDj4t_PsF9IOZfDdObrtJ3Ti7X';

    // List all photos in the specified folder
    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); // Won't console.log the photos
    res.render('gallery', { photos }); // Render the gallery page with photos
  } catch (err) {
    console.error('Error fetching photos from 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>

Error:

ReferenceError: /Users/kristiyanlyubenov/Desktop/Welldoers/views/gallery.ejs:29 27| 28| >> 29| <% photos.forEach(photo => { %> 30| " target="_blank"> 31| " alt="" /> 32| photos is not defined

1

There are 1 best solutions below

0
Linda Lawton - DaImTo On

You have a few of issues.

The first being your not passing an api key. Api keys give you access to public data. Without it your not going to be able to access the data.

The second issue is that you are using using root in parents which wont work as your root directory is not public. You should be passing ${folderId}' in parents

The third issue is something to do with the return of your promises.

I tested this with my api key and it works i can see your files

const api_key = "[Redacted]";
const {google} = require('googleapis');

const drive = google.drive({version: 'v3', auth: api_key});

const folderId = '1agwyqLRDj4t_PsF9IOZfDdObrtJ3Ti7X';
async function listFiles(authClient) {
    const res = await drive.files.list({
        pageSize: 10,
        q: `'${folderId}' in parents and (mimeType='image/jpeg' or mimeType='image/png' or mimeType='image/gif')`,
        fields: 'nextPageToken, files(id, name, webViewLink)',
    });

    const files = res.data.files;
    if (files.length === 0) {
        console.log('No files found.');
        return;
    }

    console.log('Files:');
    files.map((file) => {
        console.log(`${file.name} (${file.id})`);
    });
}

listFiles().then(res => console.log(res)).catch(console.error);

Results

Files:
Screenshot 2023-09-24 at 3.12.35.png (1xYyq1htNWt10Vy7BXasjSG9J8XH7wdEq)  (https://drive.google.com/file/d/1xYyq1htNWt10Vy7BXasjSG9J8XH7wdEq/view?usp=drivesdk)
Screenshot 2023-09-24 at 3.12.30.png (1i57A9E5N2SIadIGWdfVSoA2gggPUVt6E)  (https://drive.google.com/file/d/1i57A9E5N2SIadIGWdfVSoA2gggPUVt6E/view?usp=drivesdk)