百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

「JS小技巧」Nodejs读取Google Drive里面的文件

bigegpt 2024-08-26 10:55 2 浏览

最近在工作中遇到了一个场景:要做一个静态的网站,里面的内容是由设计编写的.md格式的内容。设计将编好的文档统一放在常用的Google Drive里面,如下图

然后我需要将这些文档下载下来导入到我的项目里面,然后进行解析编译,最后展示在网页上面。最开始,每次下载.md、删除项目里面之前的.md、再导入新的.md, 没什么问题,但是设计时不时更新一下文档,然后我每次我都要痛苦地执行上面的操作,关键是这些.md还不止一个文件夹,文档的数量也有近百个,重复工作不胜其烦。

为了解决这个问题,我想到使用NodeJS编写一个简单的脚本,直接读取Google Drive里面的文件。下面记录了一些过程

Google搜索google drive api

非常多的API, 直接找我们需要的Download

然后这里有官方提供的案例

copy到项目里面,在build文件夹下建一个test.js,将刚刚copy的脚本放在里面。但是这个脚本,我们缺少fileId,拿不到fileId就无法去下载。于是去找get方法

从list返回集里面可以找到fileId, 且参数里面传入我们的driveId(文件夹的ID)

所以,我们现在我们依赖两个API: list和get。我们先读取文件夹里面全部的文件

async function list(folderId, limit = 100) {
  let files = [];
  let pageToken = null;
  let listOptions = {
    q: `'${folderId}' in parents`,
    fields: 'files(id,name,mimeType,trashed)'
  };
  while (true) {
    if (pageToken) {
      listOptions['pageToken'] = pageToken;
    }
    let response = await drive.files.list(listOptions);
    if (!response.data.files || !response.data.files.length) {
      break;
    }
    let limitReached = false;
    for (let file of response.data.files) {
      if (file.trashed) {
        continue;
      }
      delete (file.trashed);
      files.push(file);
      if (files.length >= limit) {
        limitReached = true;
        break;
      }
    }
    pageToken = response.data.nextPageToken;
    if (limitReached || !pageToken) {
      break;
    }
  }
  return files;
}

期望返回的files如下:

[
  {
    id: '3434UTHhlvdvpFL4hdHjsxImiLPKYLYh6VpK',
    name: 'Default Page.md',
    mimeType: 'text/markdown'
  },
  {
    id: '134Za--w6fKhGSZGPc7vWAn_ejg88Sx4pqf',
    name: 'Anchor.md',
    mimeType: 'text/markdown'
  },
]

这里的id就是fileId, 然后我们就可以通过

files.forEach(file => {
  drive.files.get({ fileId: file.id, alt: 'media' }).then(res => {
		console.log('res', res.data)
    // writeFile
  });
});

到这里,基本上主要的Google Drive的API已经用完了,但是,我们知道使用Google Drive是需要登录认证,只有授权账户才能访问文件。所以接下来的工作就是获取Google Auth。


Get Google Auth

从Google API Console[https://console.cloud.google.com/apis/dashboard]进入Google Developer Console。新建一个project

填写project信息

这样,project就创建好了,我们还需要给它配置api

选择google drive

启用google drive

为了使用API, 我们创建凭据

继续


继续

继续

继续

完成后就看到生成的服务账号了,点击编辑

生成秘钥

导出为json格式,并保存到项目中credentials.json

接下来,我们就可以使用生成的凭据来获得Google Auth了

const { google } = require("googleapis");
const credentials = require("./credentials.json");
const scopes = ["https://www.googleapis.com/auth/drive"];
const auth = new google.auth.JWT(
  credentials.client_email,
  null,
  credentials.private_key,
  scopes
);
const drive = google.drive({ version: "v3", auth });

至此,我们的读取Google Drive的功能全部介绍到了。但是想要使用,还需要给对象文件(夹)share with service account email id.

这里的email来源于上面credentials.json里面的的client_email。

至此,我们就能真正访问到Google Drive里面的文件了。下面是全部的脚本

const { google } = require("googleapis");
const writeFile = require('write');
const { resolve } = require('path');

const folders = [
  {
    name: '组件文档',
    folderId: '1sfsCs5ojo4g-RJU-GamENaetNpJlpVYiNQ',
    dest: 'pages/components'
  },
  {
    name: '组件日志',
    folderId: '1MsdVAyt7_c1qsXM8ZxyVV_lxXG2_VhD6fW',
    dest: 'pages/record'
  },
  {
    name: '设计文档',
    folderId: '12IkZBRsdNjW_D0C3pKOsEOehkGv0uZO3',
    dest: 'pages/design'
  },
]

const credentials = require("./credentials.json");
const scopes = ["https://www.googleapis.com/auth/drive"];
const auth = new google.auth.JWT(
  credentials.client_email,
  null,
  credentials.private_key,
  scopes
);
const drive = google.drive({ version: "v3", auth });

// 读取文件夹里面的文件,返回的数据格式如下:
// {
//   id: '1me2MPIehUw9LeP7sj4Px-V45G_m6mIGFZ',
//   name: 'Button.md',
//   mimeType: 'text/markdown'
// }
async function list(folderId, limit = 100) {
  let files = [];
  let pageToken = null;
  let listOptions = {
    q: `'${folderId}' in parents`,
    fields: 'files(id,name,mimeType, trashed)'
  };
  while (true) {
    if (pageToken) {
      listOptions['pageToken'] = pageToken;
    }
    let response = await drive.files.list(listOptions);
    if (!response.data.files || !response.data.files.length) {
      break;
    }
    let limitReached = false;
    for (let file of response.data.files) {
      if (file.trashed) {
        continue;
      }
      delete (file.trashed);
      files.push(file);
      if (files.length >= limit) {
        limitReached = true;
        break;
      }
    }
    pageToken = response.data.nextPageToken;
    if (limitReached || !pageToken) {
      break;
    }
  }
  return files;
}

folders.forEach(folder => {
  const { folderId, dest } = folder;
  list(folderId).then(files => {
    // console.log('files', files);
    files.forEach(file => {
      drive.files.get({ fileId: file.id, alt: 'media' }).then(res => {
        writeFile(`${resolve(dest)}/${file.name}`, res.data, {encoding: 'utf-8'});
        console.log(`Download ${resolve(dest)}/${file.name} success`);
      });
    });
  });
});

最终,完成需求,解放双手

相关推荐

Docker篇(二):Docker实战,命令解析

大家好,我是杰哥上周我们通过几个问题,让大家对于Docker有了一个全局的认识。然而,说跟练往往是两个概念。从学习的角度来说,理论知识的学习,往往只是第一步,只有经过实战,才能真正掌握一门技术所以,本...

docker学习笔记——安装和基本操作

今天学习了docker的基本知识,记录一下docker的安装步骤和基本命令(以CentOS7.x为例)一、安装docker的步骤:1.yuminstall-yyum-utils2.yum-con...

不可错过的Docker完整笔记(dockerhib)

简介一、Docker简介Docker是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0协议开源。Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,...

扔掉运营商的 IPTV 机顶盒,全屋全设备畅看 IPTV!

其实现在看电视节目的需求确实大大降低了,折腾也只是为了单纯的让它实现,享受这个过程带来的快乐而已,哈哈!预期构想家里所有设备直接接入网络随时接收并播放IPTV直播(电信点播的节目不是太多,但好在非常稳...

第五节 Docker 入门实践:从 Hello World 到容器操作

一、Docker容器基础运行(一)单次命令执行通过dockerrun命令可以直接在容器中执行指定命令,这是体验Docker最快捷的方式:#在ubuntu:15.10容器中执行ech...

替代Docker build的Buildah简单介绍

Buildah是用于通过较低级别的coreutils接口构建OCI兼容镜像的工具。与Podman相似,Buildah不依赖于Docker或CRI-O之类的守护程序,并且不需要root特权。Builda...

Docker 命令大全(docker命令大全记录表)

容器生命周期管理run-创建并启动一个新的容器。start/stop/restart-这些命令主要用于启动、停止和重启容器。kill-立即终止一个或多个正在运行的容器rm-于删除一个或...

docker常用指令及安装rabbitMQ(docker安装rabbitmq配置环境)

一、docker常用指令启动docker:systemctlstartdocker停止docker:systemctlstopdocker重启docker:systemctlrestart...

使用Docker快速部署Storm环境(docker部署confluence)

Storm的部署虽然不是特别麻烦,但是在生产环境中,为了提高部署效率,方便管理维护,使用Docker来统一管理部署是一个不错的选择。下面是我开源的一个新的项目,一个配置好了storm与mono环境的D...

Docker Desktop安装使用指南:零基础教程

在之前的文章中,我多次提到使用Docker来安装各类软件,尤其是开源软件应用。鉴于不少读者对此有需求,我决定专门制作一期关于Docker安装与使用的详细教程。我主要以Macbook(Mac平台)为例进...

Linux如何成功地离线安装docker(linux离线安装httpd)

系统环境:Redhat7.2和Centos7.4实测成功近期因项目需要用docker,所以记录一些相关知识,由于生产环境是不能直接连接互联网,尝试在linux中离线安装docker。步骤1.下载...

Docker 类面试题(常见问题)(docker面试题目)

Docker常见问题汇总镜像相关1、如何批量清理临时镜像文件?可以使用sudodockerrmi$(sudodockerimages-q-fdanging=true)命令2、如何查看...

面试官:你知道Dubbo怎么优雅上下线的吗?你:优雅上下线是啥?

最近无论是校招还是社招,都进行的如火如荼,我也承担了很多的面试工作,在一次面试过程中,和候选人聊了一些关于Dubbo的知识。Dubbo是一个比较著名的RPC框架,很多人对于他的一些网络通信、通信协议、...

【Docker 新手入门指南】第五章:Hello Word

适合人群:完全零基础新手|学习目标:30分钟掌握Docker核心操作一、准备工作:先确认是否安装成功打开终端(Windows用户用PowerShell或GitBash),输入:docker--...

松勤软件测试:详解Docker,如何用portainer管理Docker容器

镜像管理搜索镜像dockersearch镜像名称拉取镜像dockerpullname[:tag]列出镜像dockerimages删除镜像dockerrmiimage名称或id删除...