最近在工作中遇到了一個場景:要做一個靜態的網站,里面的內容是由設計編寫的.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`);
});
});
});
});
最終,完成需求,解放雙手