Google Apps ScriptでZIP圧縮・解凍をやってみる【GAS】

Google Apps Scriptは、基本Google Driveで出来る事がスクリプトのメソッドで用意されています。その中でも地味ながら使う機会も多いのが、ZIPの圧縮と解凍。メールに添付して送信や受信した添付ファイルを解凍、ZIPのままスプレッドシートに取り込むなどなど使いドコロは、結構あると思います。

ユーザに作業をあまりやらせない上でもこのメソッドは習得しておきたい所です。しかし、このメソッドは圧縮と解凍使う方法は同じでも、その処理にちょっと違いがあるので、注意が必要です。

使用するクラスやメソッド

Google Apps ScriptのUtilitiesクラスはZIP圧縮だけでなく、hash値を作ったりBase64エンコード、文字列のフォーマットやSleepなど様々な雑多なコマンドを実行できるクラスで、非常に便利なものが詰まっています。JavaScriptで書いても良いのですが、Google Apps内に用意されているこれらメソッドのほうが利便性は高いので、積極的に使いましょう。

ZIP圧縮するコード

フォルダ内ファイルの圧縮

//圧縮対象フォルダのID
var zipfolder = "ここに圧縮対象フォルダのIDを入れる"

//圧縮ルーチン
function zippress(){
  //圧縮するファイルが入ってるフォルダを指定
  var folder = DriveApp.getFolderById(zipfolder);
  
  //カレントフォルダを取得する
  var curdir = folder.getId();
  
  //zip圧縮を行う
  var zipman = Utilities.zip(getBlobs(folder, ''), folder.getName()+'.zip')
  folder.getParents().next().createFile(zipman);

  //メッセージ
  SpreadsheetApp.getUi().alert("圧縮完了");
}

//指定フォルダ内のファイルを配列にBlobで入れる関数
function getBlobs(rootFolder, path) {
  var blobs = [];
  var files = rootFolder.getFiles();
  while (files.hasNext()) {
    var file = files.next().getBlob();
    file.setName(path+file.getName());
    blobs.push(file);
  }
  var folders = rootFolder.getFolders();
  while (folders.hasNext()) {
    var folder = folders.next();
    var fPath = path+folder.getName()+'/';
    blobs.push(Utilities.newBlob([]).setName(fPath)); 
    blobs = blobs.concat(getBlobs(folder, fPath));
  }
  return blobs;
}

今回は、特定のフォルダ内にあるファイル群をフォルダ名と同じファイル名をつけて、その対象のフォルダの中にzipを保存するというスクリプトです。ZIPで圧縮した後に、フォルダの名前と同じ名前をファイル名にするために、renameメソッドで名前の変更をしています。

  • ZIPで固めた後はcreateFileでファイルを生成してあげないとZIPファイルが出来ませんので注意。
  • ファイル類はすべてBlobで取得し、配列に入れてゆきます。

リモートサーバ上のファイルの圧縮

UrlfetchAppと組み合わせることで、リモートサーバ上にあるファイルをBlobで取得し、ZIPで固めるといった離れ業もする事が可能です。逆にリモートサーバ上のZIPファイルを取得してGoogle Drive上に解凍する事も可能です。以下はリモートサーバ上のファイルを圧縮して、スプレッドシートのあるフォルダ内にremote.zipとして生成するコードです。

//リモートサーバにあるファイルを直接ZIPで固める
function remotezip(){
  //配列を用意する
  var array = [];
  
  //サーバー上のファイルのURLを指定する
  var remotefile1 = "https://officeforest.org/wp/public/remote/coin.png";
  var remotefile2 = "https://officeforest.org/wp/public/remote/passion.jpg";
  
  //リモートファイルをBlobで取得
  var file1 = UrlFetchApp.fetch(remotefile1).getBlob();
  var file2 = UrlFetchApp.fetch(remotefile2).getBlob();
  
  //配列にpushする
  array.push(file1);
  array.push(file2);
  
  //ファイルをZIPで固める
  var zip = Utilities.zip(array, "remote.zip");
  
  //カレントディレクトリを取得する
  var ssid = SpreadsheetApp.getActiveSpreadsheet().getId();
  var curdir = DriveApp.getFolderById(driveman(ssid));
  
  //ZIPファイルを生成する
  curdir.createFile(zip);

}

ZIP解凍するコード

var zipfile = "ここにZIPファイルのIDを入れる";

//ZIP解凍
function zipmelt(){
  //解凍する対象のファイルを取得
  var zipblob = DriveApp.getFileById(zipfile);
  
  //ファイル解凍の準備
  var unzipfile = Utilities.unzip(zipblob);
  
  //解凍先フォルダはカレントディレクトリにする
  var curdir = driveman(zipfile);
  
  //フォルダを作成してその中にunzipしたファイル群を入れる
  var newFolder = DriveApp.getFolderById(curdir).createFolder("ZIP解凍")
  for(i=0;i<unzipfile.length;i++){
    newFolder.createFile(unzipfile[i]);
  }
  
  //メッセージ
  SpreadsheetApp.getUi().alert("解凍完了");
}

//カレントフォルダを返す関数
function driveman(id){
  var parentsfolder = DriveApp.getFileById(id).getParents();
  while (parentsfolder.hasNext()) {
   var folder = parentsfolder.next();
   var idval = folder.getId();
   return idval;
  }
}

今回は、passion.zipというファイルをカレントフォルダ内にzipmeltというフォルダを作成し、その中に全て解凍するというルーチンです。

zip作成とは異なりちょっと面倒なファイル操作が必要です。zipファイルの中身の取り出しとcreateFileで作る点はほぼ同じなのですが、一発でやってくれないので、一つ一つ取り出す為にforループを書く必要性があります。逆に言えば必要なものだけ解凍するコードも書けるわけです。zipファイルはBlob配列で格納されていますので、getBlobで取得する必要性があります。必ず、getBlobしてからunzipしなければなりません。

ポイント

このzipとunzipメソッドですが、Driveにあるファイルを扱うだけにとどまらず、外部URLも扱えます。つまり、Dropboxなどに格納してあるzipファイルなども扱えるようになっています。その場合、配列にURLを格納してzipメソッドやunzipメソッドを実行します。今回は適当に作ってますが、メールに添付や特定のフォルダに保存など、もう一工夫付け加えるとなお、活用できるのではと思います。特にメール添付の場合、例えば、リファレンスにあるように外部URLのファイルをZIPできるので、DropBoxの公開URLを元に圧縮して、送りつけるなんて芸当も可能です。

  • ちなみに、zipの他にUtilities.gzipやUtilities.ungzipもある。
  • 暗号化ZIPの圧縮解凍には対応していません。

関連リンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)