2020-04-26

批次下載 Google Drive 的檔案

有很多公司有提供雲端服務,Google的雲端硬碟服務相信最廣為人知及使用
上載檔案到自己的 Google雲端帳戶,或從自己的 Google雲端帳戶下載檔案,是非常簡單
最近幫朋友剪輯影片,對方將大量檔案存放到 Google雲端硬碟,每個檔案都超過 1GB
發現下載大量大型載檔案非常不方便……

一般從其他公開的 Google雲端帳戶的位置下載檔案都是使用網頁瀏覽器
如果只是一個檔案便會立即下載;但如果是多個檔案,便需要先將選取的檔案壓縮成一個 ZIP檔案,才開始下載
如果檔案不是大型檔案,時間還不太長;但如果是大型檔案,先壓縮再下載,所花的時間便會很長
而且這種方法受制於相同 Google雲端的資料夾的檔案,如果檔案分散在不同資料夾,仍然需要逐一處理
這個狀態會非常浪費時間,而且需要安份地在電腦前(或最少需要遙距控制)手動操作

Google檔案類型

由於 Google雲端硬碟 與 Google文件編輯器 整合
Google 有幾種檔案能夠轉換成一般檔案
Google檔案類型MIME類型可轉轉換格式
Google文件application/vnd.google-apps.documentDOCX, ODT, RTF, PDF, TXT, HTML.ZIP, EPUB
Google試算表application/vnd.google-apps.spreadsheetXLSX, ODS, PDF, HTML.ZIP, CSV, TSV
Google簡報application/vnd.google-apps.presentationPPTX, ODP, PDF, TXT, JPG, PNG, SVG
Google繪圖application/vnd.google-apps.drawingPDF, JPG, PNG, SVG
Google表格application/vnd.google-apps.form
Google網頁application/vnd.google-apps.site
Google App Scriptapplication/vnd.google-apps.scriptJSON
Google Jamapplication/vnd.google-apps.jamPDF
下載 Google檔案 與 一般檔案 時會有分別
Google文件格式 ,下載連結為
https://docs.google.com/document/u/0/d/<google-drive-file-id>/export?format=<extension>
Google試算表格式 ,下載連結為
https://docs.google.com/spreadsheets/u/0/d/<google-drive-file-id>/export?format=<extension>
Google簡報格式 ,下載連結為
https://docs.google.com/presentation/d/<google-drive-file-id>/export/<extension>?pageid=<page-id>
Google繪圖格式 ,下載連結為
https://docs.google.com/drawings/d/<google-drive-file-id>/export/<extension>?pageid=p
雖然 Google App Script 及 Google Jam 都能夠匯出,但暫時必須在 Google雲端硬碟進行
一般檔案 ,下載連結為
https://drive.google.com/uc?id=<google-drive-file-id>
google-drive-file-idGoogle雲端檔案的ID
extension可以轉換的格式
page-idGoogle簡報的頁面ID ,但不是頁數 ;當 page-id 為 p 時,為全部頁面

小於或等於100MB

當一般檔案小於或等於100MB時,下載連結會直接下載檔案

大於100MB

見下文
當一般檔案大於100MB時,下載連結並不會直接下載檔案,而是詢問是否需要下載

Google API Console

https://console.developers.google.com 並登入自己的Google帳戶

見下文
資訊主頁 > 建立專案

見下文
設定 專案名稱 後按 建立

見下文
啟用 API 和服務

見下文
搜尋 Google Drive API

見下文
啟用 Google Drive API

見下文
建立憑證

見下文
API金鑰

見下文
有需要可以 修改 API金鑰的名稱 方便管理
應用程式限制 讓 API金鑰 更加安全
然後按 建立


見下文
由於 API 金鑰能透過閣下的許可使用 Google 各種 API 服務,因此不要透露給其他人使用

見下文
若不慎洩漏,請立即刪除該 API 金鑰 或 重設該 API 金鑰
然後按 儲存

程式碼

因此在下使用編寫一個簡單的 腳本程式 來下載 Google雲端的檔案

見下文
當使用 Google Drive API 獲取檔案的 MIME類型,便可以區分 Google檔案 及 一般檔案
由於當一般檔案 小於或等於100MB時,會使用 HTTP狀態碼 (HTTP Status Code) 會傳回 302 才下載檔案
而 大於100MB時,會傳回 200 ,需要手動按下載的連結才能下載檔案
該連結會附加 confirm 的參數,並且需要具備 Cookie 才允許下載檔案
由於在下同樣希望懶惰一點,因此使用 HTTP狀態碼 識別

#!/bin/bash

APIKEY="your-api-key"
COOKIE="cookie.txt"

function downloadFolder() {
    JSON=`curl --request "GET" -sL "https://www.googleapis.com/drive/v3/files?q='${1}'+in+parents&key=${APIKEY}" | jq ".files"`
    LENGTH=`echo "${JSON}" | jq ".|length"`
    i="0"
    while [ "${i}" -lt "${LENGTH}" ]; do
        ID=`echo "${JSON}" | jq -r ".[${i}].id"`
        NAME=`echo "${JSON}" | jq -r ".[${i}].name"`
        MIME=`echo "${JSON}" | jq -r ".[${i}].mimeType"`
        case "${MIME}" in
            "application/vnd.google-apps.folder")
                echo -e "run \e[1;92mdownloadFolder \"${ID}\"\e[0m to download this folder next time"
            ;;
            "application/vnd.google-apps.document")
                downloadDocument "${ID}" "${NAME}"
            ;;
            "application/vnd.google-apps.spreadsheet")
                downloadSpreadsheet "${ID}" "${NAME}"
            ;;
            "application/vnd.google-apps.presentation")
                downloadPresentation "${ID}" "${NAME}"
            ;;
            "application/vnd.google-apps.drawing")
                downloadDrawing "${ID}" "${NAME}"
            ;;
            "application/vnd.google-apps."*)
                echo -e "\e[1;91mMIME type \"${MIME}\" cannot be exported\e[0m"
            ;;
            *)
                downloadFile "${ID}" "${NAME}"
            ;;
        esac
        i=`echo "${i} + 1" | bc`
    done
}

function downloadFile() {
    NAME="${2}"
    if [ "${NAME}" = "" ]; then
        NAME=`curl --request "GET" -sL "https://www.googleapis.com/drive/v3/files/${1}?key=${APIKEY}" | jq -r ".name"`
    fi
    LINK="https://drive.google.com/uc?export=download&id=${1}"
    CODE=`curl -I --request "GET" -sL "${LINK}" | head -1 | sed -r 's/.+([0-9]{3}).+/\1/g'`
    if [ "${CODE}" = "200" ]; then
        CONFIRM=`wget --save-cookies="${COOKIE}" -q "${LINK}" -O- | grep 'confirm=' | sed -r 's/.+confirm=([^&]+)&amp;.+/\1/g'`
        wget --load-cookies="${COOKIE}" "${LINK}&confirm=${CONFIRM}" -O "${NAME}"
        rm "${COOKIE}"
    elif [ "${CODE}" = "302" ]; then
        wget "${LINK}" -O "${NAME}"
    fi
}

function downloadDocument() {
    NAME="${2}"
    if [ "${NAME}" = "" ]; then
        NAME=`curl --request "GET" -sL "https://www.googleapis.com/drive/v3/files/${1}?key=${APIKEY}" | jq -r ".name"`
    fi
    wget "https://docs.google.com/document/u/0/d/${1}/export?format=pdf" -O "${NAME}.pdf"
}

function downloadSpreadsheet() {
    NAME="${2}"
    if [ "${NAME}" = "" ]; then
        NAME=`curl --request "GET" -sL "https://www.googleapis.com/drive/v3/files/${1}?key=${APIKEY}" | jq -r ".name"`
    fi
    wget "https://docs.google.com/spreadsheets/u/0/d/${1}/export?format=pdf" -O "${NAME}.pdf"
}

function downloadPresentation() {
    NAME="${2}"
    if [ "${NAME}" = "" ]; then
        NAME=`curl --request "GET" -sL "https://www.googleapis.com/drive/v3/files/${1}?key=${APIKEY}" | jq -r ".name"`
    fi
    wget "https://docs.google.com/presentation/d/${1}/export/pdf?pageid=p" -O "${NAME}.pdf"
}

function downloadDrawing() {
    NAME="${2}"
    if [ "${NAME}" = "" ]; then
        NAME=`curl --request "GET" -sL "https://www.googleapis.com/drive/v3/files/${1}?key=${APIKEY}" | jq -r ".name"`
    fi
    wget "https://docs.google.com/drawings/d/${1}/export/pdf?pageid=p" -O "${NAME}.pdf"
}

downloadFolder "google-drive-folder-id"
downloadDocument "google-drive-document-id"
downloadSpreadsheet "google-drive-spreadsheet-id"
downloadPresentation "google-drive-presentation-id"
downloadDrawing "google-drive-drawing-id"
downloadFile "google-drive-file-id"
上述程式看似很複雜,其實只是使用 CURL, Wget, jq 便可以簡次下載 Google雲端的檔案
google-drive-*-id 取代為需要下載的 Google雲端檔案的ID
APIKEY 修改為閣下的 Google API Console 的 API金鑰,便可以使用

總結

雖然不一定是最簡單最方便的方法,但可以自動化下載程序,對需要在 Google雲端硬碟 下載大量大型檔案,算是一種替待方法
其實 Google Drive API 已經提供 Java, Python, Node.js 的函式庫,亦有第三方 gdrive 可以使用,可以更快開發自己的 Google Drive 程式
不過在下只是執行簡單操作,因此沒有使用大型的函式庫

參考資料

沒有留言 :

張貼留言