最近在工作中遇到了一个场景:要做一个静态的网站,里面的内容是由设计编写的.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`);
});
});
});
});
最终,完成需求,解放双手