GoogleAppsScript

Google Apps Scriptを使ってGoogle Drive上のファイルを分割する

概要

Google Drive内にあるサイズの大きなファイルをGoogle Apps Script(GAS)で処理しようとすると、扱うことのできるサイズに制限が設けられているために直接処理することはできません。そのため、ファイルを分割することを考えます。バイト配列や文字列に変換してから分割という方法もあるのですが、この場合、GASで扱うことのできるblobの最大サイズが50 MB (52,428,800 bytes)と制限されているため、50 MBよりも大きなサイズのファイルを扱う場合にどのようにして分割しようか悩まされました。悩んだ結果、50 MB以上の大きなファイルをGoogle Driveへアップロードするために用意されているResumable uploadがありますが、Resumable downloadもあってよいのではないかと思い、これを探したところ、Partial downloadなる機能を発見しました。これはまさにResumable downloadのためのものです。これを利用することで50 MB以上のファイルでも無事に分割して処理することができるようになりました。この記事ではPartial downloadを用いたファイル分割について紹介します。

使い方

このサンプルを使用する際は、事前にGoogleの拡張サービスとAPIコンソールでDrive APIを有効にしてください。

  1. Googleの拡張サービス

    • スクリプトエディタから リソース -> Googleの拡張サービス を開き、Drive APIを有効にしてください。
  2. APIコンソール

    • スクリプトエディタの「リソース」 -> 「Cloud Platformプロジェクト」を開きます。
    • 「このスクリプトが現在関連付けられているプロジェクト:」の下のリンクをクリックします。
    • 「スタートガイド」の「API を有効化し、鍵などの認証情報を取得」をクリックします。
    • ダッシュボードにDrive APIが見えている場合はそれをクリックします。見えていない場合は、左側のサイドバーにある「ライブラリ」をクリックします。
    • 「APIとサービスを検索」へ Drive API と入力して検索します。
    • 表示された中からDrive APIをクリックします。
    • ここでDrive APIを有効にします。ボタンをクリックしてから少しの待ち時間があります。

次に、スクリプトの一番上にあるfileId, chunk, fileNameを使用する環境に合わせて変更してください。

  • fileIdは分割したいファイルのファイルIDです。
  • chunkは分割したいそれぞれのファイルのサイズです。最後のファイルは残りのサイズが割り当てられます。
  • fileNameは分割したファイルのファイル名です。ファイル名の後に通し番号が付加されます。

サンプルスクリプト

// 下記3つの変数は環境に合わせて修正してください。
var fileId = "### fileId ###";
var chunk = 123456; // Set chunk size.
var fileName = "sample";


var accessToken = ScriptApp.getOAuthToken();
var baseUrl = "https://www.googleapis.com/drive/v3/files/";

// Retrieve file size.
var url1 = baseUrl + fileId + "?fields=size";
var params1 = {
    method: "get",
    headers: {Authorization: "Bearer " + accessToken},
};
var fileSize = Number(JSON.parse(UrlFetchApp.fetch(url1, {headers: {Authorization: "Bearer " + accessToken}}).getContentText()).size);

// Calculate number of output files.
var start = 0;
var end = chunk;
var loop = Math.floor(fileSize / chunk);
loop = fileSize % chunk > 0 ? loop + 1 : loop;

// Split large file by chunk size (bytes).
var results = [];
var url2 = baseUrl + fileId + "?alt=media";
for (var i = 0; i < loop; i++) {
    var params = {
        method: "get",
        headers: {
            Authorization: "Bearer " + accessToken,
            Range: "bytes=" + start + "-" + end,
        },
    };
    var f = Drive.Files.insert({title: fileName + (i + 1)}, UrlFetchApp.fetch(url2, params).getBlob());
    results.push({name: f.title, id: f.id});
    start += chunk + 1;
    end = start + chunk;
}
Logger.log(results);

サンプル

他の状況として、大きなサイズのCSVファイルを分割しつつ、スプレッドシートに変換するサンプルはこちらをご覧ください。