Google Drive API返回200成功但未导出PDF文件的问题
问题:调用Google Drive API v3导出GDOC为PDF返回HTTP 200,但本地未生成目标文件
问题详情
用户通过Node.js脚本调用Google Drive API v3导出GDOC文件为PDF,脚本执行后返回HTTP 200状态码,但本地未生成目标PDF文件。期望实现与手动下载PDF一致的效果,此前导出纯文本的方式已失效。
原因分析
HTTP 200状态码说明API请求已成功,Google Drive服务端已经返回了PDF的二进制数据,但当前脚本仅发起了导出请求并打印了状态码,没有将响应中的PDF数据写入本地文件,因此看不到生成的文件。
修复后的脚本
修改exportPdf函数,添加文件写入逻辑,将API返回的二进制数据保存到本地:
// 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', responseType: 'stream' // 指定响应类型为流,更适合处理大文件 }); // 将响应流写入本地文件 const writeStream = fs.createWriteStream('exported.pdf'); result.data.pipe(writeStream); return new Promise((resolve, reject) => { writeStream.on('finish', () => { console.log('PDF文件已成功生成'); resolve(result); }); writeStream.on('error', (err) => { reject(err); }); }); } catch (err) { throw err; } } authorize().then(exportPdf).catch(console.error);
关键修改点
- 添加
responseType: 'stream'参数:指定API响应以流的形式返回,更高效处理PDF这类可能较大的文件,避免内存占用过高。 - 创建文件写入流:使用
fs.createWriteStream创建本地文件的写入流,将API返回的数据流通过pipe方法写入文件。 - 监听流的完成/错误事件:确保文件写入完成后再返回结果,同时处理写入过程中的异常。
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

