【问题标题】:Download public images from google drive in Node.JS在 Node.JS 中从谷歌驱动器下载公共图像
【发布时间】:2021-03-15 05:47:23
【问题描述】:

我在 googledrive 上有一组图像,并且我有一个指向每个图像的链接列表。它们可能是公开的,也可能不是公开的(知道链接的任何人)。我想将它们保存在本地并单独嵌入到网页中,因为直接将它们嵌入到 img 标签中会导致图像加载延迟。

我需要通过 Node.JS 脚本以编程方式下载它们。 Node.JS 脚本是我构建管道的一部分,因此我不能完全使用 gdown(python 包)。

我尝试了 google drive API,但 OAuth 令牌每小时都会过期,而且我的构建每周都在 cron 作业中,同时提交到存储库。

我有什么选择?

这是一个例子

[
  {
    "name": "A",
    "photoUrl": "https://drive.google.com/uc?export=view&id=1km3V6PP70MTUsNWFEgdVea6jv-0BMnRT"
  },
  {
    "name": "B",
    "photoUrl": "https://drive.google.com/uc?export=view&id=1km3V6PP70MTUsNWFEgdVea6jv-0BMnRT"
  },
]

【问题讨论】:

  • 为了正确理解您的问题,请问您目前的情况和您的目标是什么? 1.在您的情况下,所有图像文件都是公开共享的? 2. 文件中一个文件的最大大小是多少? 3.在你的情况下,你可以使用request模块来下载文件吗? 4. 您将如何使用下载的文件?例如,您想将下载的文件创建为文件?或者您想将下载的文件用作二进制数据?
  • 1.其中大多数是,但如果不是,我不会下载该图像。 2. 最大 3MB 3. 我试过 https.get(url, res => res.pipe(file)) 但获取请求似乎失败了。 4. 我正在使用一个静态站点生成器,它将在预处理后在生成的 html 中添加 img 元素
  • 感谢您的回复。根据您的回复,所有文件中一个文件的最大文件大小为 3 MB,并且您希望在文件公开共享时将文件下载为二进制数据。并且您想将数据与其他进程一起使用。我的理解正确吗?如果我的理解是正确的,你能提供样品a list of links吗?当您无法提供示例链接时,请不要担心。那时,我想提出一个使用文件ID的示例脚本。
  • 我在原始问题中添加了参考 json。您可以将图像保存为${name}.jpg
  • 感谢您回复并添加更多信息。根据您的回复,我提出了一个示例脚本作为答案。你能确认一下吗?如果这不是您期望的方向,我深表歉意。

标签: javascript node.js download


【解决方案1】:

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

  • 所有文件中一个文件的最大文件大小为 3 MB。

  • 当文件被公开共享时,您想下载该文件,作为使用 Node.js 的二进制数据。

    • 在这种情况下,您可以使用request 模块。
  • 您想将数据用于其他进程。

  • 您的清单如下。而且,您想使用像${name}.jpg 这样的文件名。由此,所有文件都是JPEG文件。

      [
        {
          "name": "A",
          "photoUrl": "https://drive.google.com/uc?export=view&id=1km3V6PP70MTUsNWFEgdVea6jv-0BMnRT"
        },
        {
          "name": "B",
          "photoUrl": "https://drive.google.com/uc?export=view&id=1km3V6PP70MTUsNWFEgdVea6jv-0BMnRT"
        },
      ]
    

在这种情况下,下面的示例脚本怎么样?

示例脚本:

const fs = require("fs");
const request = require("request");

async function main() {
  const download = ({ name, url }) =>
    new Promise((resolve, reject) => {
      request({ url: url, encoding: null }, (err, res, buf) => {
        if (err) {
          reject(err);
          return;
        }
        if (res.headers["content-type"].includes("text/html")) {
          console.log(`This file (${url}) is not publicly shared.`);
          resolve(null);
          return;
        }

        // When you use the following script, you can save the downloaded image data as the file.
        fs.writeFile(
          name,
          buf,
          {
            flag: "a",
          },
          (err) => {
            if (err) reject(err);
          }
        );

        resolve(buf);
      });
    });

  // This is a sample list from your question.
  const list = [
    {
      name: "A",
      photoUrl:
        "https://drive.google.com/uc?export=view&id=1km3V6PP70MTUsNWFEgdVea6jv-0BMnRT",
    },
    {
      name: "B",
      photoUrl:
        "https://drive.google.com/uc?export=view&id=1km3V6PP70MTUsNWFEgdVea6jv-0BMnRT",
    },
  ];

  // 1. Create filename and convert the URL for downloading.
  const reqs = list.map(({ name, photoUrl }) => ({
    name: `${name}.jpg`,
    url: `https://drive.google.com/uc?export=download&id=${
      photoUrl.split("=")[2]
    }`,
  }));
  
  // 2. Download the files.
  const buffers = await Promise.all(reqs.map((obj) => download(obj)));
  console.log(buffers);
}

main();
  • 您的 URL 将转换为 webContentLink。这样,当文件大小较小(如 3 MB)时,可以使用webContentLink 下载文件。
  • 在这个示例脚本中,当文件被公开共享时,文件被下载并保存。此外,您可以将下载的数据用作缓冲区。在这种情况下,当文件未公开共享时,将返回 null
  • 在您的情况下,文件列表中的所有文件都是 JPEG 图像。使用这个,通过检查响应头的内容类型,当不包含text/html时,可以认为该文件没有公开共享。

注意:

  • 当您要下载大文件时,我建议您使用 API 密钥下载。这样,您的脚本可以简单地修改。当您无法使用 API 密钥时,您可以使用this thread 的流程进行下载。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-05
    • 1970-01-01
    • 1970-01-01
    • 2020-12-28
    • 1970-01-01
    • 2022-08-18
    • 2017-06-01
    相关资源
    最近更新 更多