node.jsgoogle-drive-apiexport-to-pdf

Google Drive API Returns 200 (HTTP Success) for testing pdf export but no file


The entire test script is as follows:

// File export test: Authorization code: https://gist.github.com/LindaLawton/76bef3ab760f335d43eccaf481e0b4d0 
// Google Ref https://github.com/googleworkspace/node-samples/blob/main/drive/snippets/drive_v3/file_snippets/export_pdf.js

const fs = require('fs');
const fsp = fs.promises;

const path = require('path');
const process = require('process');
const {authenticate} = require('@google-cloud/local-auth');
const {google} = require('googleapis');

// If modifying these scopes, delete token.json.
const SCOPES = ['https://www.googleapis.com/auth/drive'];
// File id of the file to download = ocrTransfer folder in My Drive
const FILEID = '1_h-GsdKAqmu0hmZAmGslfqvE7W9ppMlt2WNGhi9diYk';

// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
const TOKEN_PATH = path.join(process.cwd(), 'DownloadFileToken.json');
const CREDENTIALS_PATH = 'C:\\googleDriveDev\\credentials.json';

/**
 * Reads previously authorized credentials from the save file.
 *
 * @return {Promise<OAuth2Client|null>}
 */
async function loadSavedCredentialsIfExist() {
    try {
        const content = await fsp.readFile(TOKEN_PATH);
        const credentials = JSON.parse(content);
        return google.auth.fromJSON(credentials);
    } catch (err) {
        return null;
    }
}

/**
 * Serializes credentials to a file compatible with GoogleAUth.fromJSON.
 *
 * @param {OAuth2Client} client
 * @return {Promise<void>}
 */
async function saveCredentials(client) {
    const content = await fsp.readFile(CREDENTIALS_PATH);
    const keys = JSON.parse(content);
    const key = keys.installed || keys.web;
    const payload = JSON.stringify({
        type: 'authorized_user',
        client_id: key.client_id,
        client_secret: key.client_secret,
        refresh_token: client.credentials.refresh_token,
    });
    await fsp.writeFile(TOKEN_PATH, payload);
}

/**
 * Load or request or authorization to call APIs.
 *
 */
async function authorize() {
    let client = await loadSavedCredentialsIfExist();
    if (client) {
        return client;
    }
    client = await authenticate({
        scopes: SCOPES,
        keyfilePath: CREDENTIALS_PATH,
    });
    if (client.credentials) {
        await saveCredentials(client);
    }
    return client;
}


/**
 * Download a Document file in PDF format
 * @param{string} fileId file ID
 * @return{obj} file status
 * */

async function exportPdf(authClient) {
  
  const service = google.drive({version: 'v3', auth: authClient});

  try {
    
    const result = await service.files.export({
      fileId: FILEID,
      mimeType: 'application/pdf',
    });
    console.log(result.status);
    return result;
  } catch (err) {
    // TODO(developer) - Handle error
    throw err;
  }
}

authorize().then(exportPdf).catch(console.error);

Output:

C:\googleDriveDev>node ./exportTest1.js
200

Why does this return indicate success but the file does not download?

I am using GDOC files by getting the ID from the URL. To me the script should do the same as: Open document in Google Drive> Choose File> Download > PDF Document (.pdf)

In the past have been able to export gdocs as plain text files. But that option no longer works so I am trying another approach.


Solution

  • Modification points:

    About your question of Why does this return indicate success but the file does not download?, when I saw your showing script, result of const result = await service.files.export({,,,}) in the function exportPdf is not used. I guessed that this might be the reason for your current issue. If you want to save the exported data as a file, how about the following modification?

    Modified script:

    In your showing script, please modify it as follows.

    From:

    async function exportPdf(authClient) {
      
      const service = google.drive({version: 'v3', auth: authClient});
    
      try {
        
        const result = await service.files.export({
          fileId: FILEID,
          mimeType: 'application/pdf',
        });
        console.log(result.status);
        return result;
      } catch (err) {
        // TODO(developer) - Handle error
        throw err;
      }
    }
    
    authorize().then(exportPdf).catch(console.error);
    

    To:

    async function exportPdf(authClient) {
      const service = google.drive({ version: "v3", auth: authClient });
    
      try {
        const result = await service.files.export(
          {
            fileId: FILEID,
            mimeType: "application/pdf",
          },
          { responseType: "stream" } // Added
        );
        console.log(result.status);
        return result;
      } catch (err) {
        // TODO(developer) - Handle error
        throw err;
      }
    }
    
    authorize()
      .then(exportPdf)
      .then(({ data }) => { // Added
        const destFile = fs.createWriteStream("sample.pdf"); // Please set the path and the output filename.
        data
          .on("end", function () {
            console.log("Done.");
          })
          .on("error", function (err) {
            console.error(err);
            return process.exit();
          })
          .pipe(destFile);
      })
      .catch(console.error);
    

    When this modified script was run, I confirmed that the file of FILEID could be correctly exported and the exported file could be saved as a file.

    Note: