【问题标题】:nodejs google drive api file download error with readablestream objectnodejs google drive api文件下载错误与可读流对象
【发布时间】:2020-07-19 23:22:05
【问题描述】:

我正在尝试使用 google drive api V3 实现从 google drive 下载文件的功能。 下面是我的代码。

service.files.get({
    auth: this.oauth2Client,
    fileId: fileId,
    alt: 'media'
}, {responseType: "stream"}, function (err, response) {
    console.log(response);
    response.data
    .on('end',() => {
        console.log('Done');
    })
    .on('error', (err) => {
        console.log('Error during download', err);
    })
    .on('data', d=> {
        progress += d.length;

        if (process.stdout.isTTY) {
            process.stdout.clearLine();
            process.stdout.cursorTo(0);
            process.stdout.write('Download ${progress} bytes');
        }
    })
    .pipe(dest);
})

当我运行代码时,我得到了这个错误。
response.data.on is not a function
不仅 on 功能,而且 pipe 功能也不起作用。 我已经检查过 response.data 是 Readablestream 的对象。

有什么想法吗?

更新
下面是 GoogleDriveSyn 类的完整代码。 getAllFilesInFolder 函数工作正常。


const path = require('path')
const {google} = require('googleapis');
const fs = require('fs');
const service = google.drive('v3');

class GoogleDriveSyn {
    constructor(auth) {
        var apiKeys = JSON.parse(fs.readFileSync('config.json'));
        this.oauth2Client = new google.auth.OAuth2(
            apiKeys['CLIENT_ID'],
            apiKeys['SECRET_ID'], 
            "http://localhost:8080" 
        );
        this.oauth2Client.credentials = auth;
        this.directory = localStorage.getItem('directory');
    }

    getAllFilesInFolder(folderId) {
        var query = '"' + folderId + '"' + ' in parents and mimeType!="application/vnd.google-apps.folder"';
        service.files.list({
            auth: this.oauth2Client,
            q: query,
            pageSize: 50,
            fields: 'nextPageToken, files(id, name, modifiedTime, kind, createdTime, thumbnailLink, mimeType, size, webContentLink)'
        }, function(err, response) {
            if (err) {
                console.log('The API returned an error: ' + err);
                return;
              }
              console.log(response);
              return response
        })
    }

    downloadFile(fileId, filePath, fileName) {
        var fullPath = path.join(this.directory, filePath, fileName);
        var dest = fs.createWriteStream(fullPath);
        let progress = 0;

        service.files.get({
            auth: this.oauth2Client,
            fileId: fileId,
            alt: 'media'
        }, {responseType: "stream"}, function (err, response) {
            console.log(response);
            response.data
            .on('end',() => {
                console.log('Done');
            })
            .on('error', (err) => {
                console.log('Error during download', err);
            })
            .on('data', d=> {
                progress += d.length;

                if (process.stdout.isTTY) {
                    process.stdout.clearLine();
                    process.stdout.cursorTo(0);
                    process.stdout.write('Download ${progress} bytes');
                }
            })
            .pipe(dest);
        })
    }
}

module.exports = GoogleDriveSyn;

另外,下面是downloadFile 函数内部的响应日志。

{config: {…}, data: ReadableStream, headers: {…}, status: 200, statusText: ""}
config: {url: "https://www.googleapis.com/drive/v3/files/1zcxy0wWsPuWINMY8FP_bjR4nrnj6t8eD?alt=media", method: "GET", responseType: "stream", headers: {…}, paramsSerializer: ƒ, …}
data: ReadableStream {locked: false}
headers: {alt-svc: "h3-29=":443"; ma=2592000,h3-27=":443"; ma=2592000,…3"; ma=2592000,quic=":443"; ma=2592000; v="46,43"", cache-control: "private, max-age=0, must-revalidate", content-disposition: "attachment", content-length: "12", content-type: "text/plain", …}
status: 200
statusText: ""
__proto__: Object

【问题讨论】:

  • 我可以问你关于你的问题吗? 1. 我们可以认为您的授权脚本可以从 Google Drive 下载文件吗? 2. 请问您要下载的文件类型。因为在你的脚本中,除了 Google Docs 之外的文件都可以下载。当您要下载 Google Docs 文件时,需要更改下载方式。
  • 在不知道service.files.get 的情况下有点难以回答,但我认为response 是使用on 方法的对象,即将response.data.on(..) 更改为response.on(..)
  • 这可能是授权问题;因此没有收到回复的原因。你应该在做任何事情之前检查错误。
  • @Morfinismo :授权很好。我收到状态码 200 的响应。
  • @Tanaike:1. 是的。授权下载文件的作品。 2. 我正在使用文本文件进行测试。

标签: node.js google-api google-drive-api


【解决方案1】:

我相信你的目标和情况如下。

  • 您想从 Google 云端硬盘下载文本文件。
  • 您的授权脚本运行良好。所以this.oauth2Client可以用来下载文件。

修改点:

  • 在我的环境中,我确认您的脚本有效。但是在您的问题中,您说发生了response.data.on is not a function 的错误。所以在本次修改中,downloadFile修改如下。

  • 首先,请确认您使用的 Node.js 的 googleapis 版本。在这种情况下,请使用最新版本的 googleapis for Node.js。目前阶段,最新版本为googleapis@55.0.0

    • 如果您使用旧的,我认为您的问题的原因可能是这个。
  • 在您的脚本中,'Download ${progress} bytes' 不正确。在这种情况下,请将其用作模板文字。这样就可以看到进度信息了。

修改脚本:

downloadFile(fileId, filePath, fileName) {
  var fullPath = path.join(this.directory, filePath, fileName);
  var dest = fs.createWriteStream(fullPath);
  let progress = 0;
  return drive.files
    .get(
      { auth: this.oauth2Client, fileId: fileId, alt: "media" },
      { responseType: "stream" }
    )
    .then((response) => {
      return new Promise((resolve, reject) => {
        response.data
          .on("end", () => {
            resolve("\nDone");
          })
          .on("error", (err) => {
            reject(err);
          })
          .on("data", (d) => {
            progress += d.length;
            if (process.stdout.isTTY) {
              process.stdout.clearLine();
              process.stdout.cursorTo(0);
              process.stdout.write(`Download ${progress} bytes`);
            }
          })
          .pipe(dest);
      });
    });
}

参考:

【讨论】:

    猜你喜欢
    • 2018-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 1970-01-01
    相关资源
    最近更新 更多