質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.49%

GASでドライブに複数ファイルをアップロード・圧縮したい

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 4,293

score 12

前提・実現したいこと

Google Apps Scriptについて質問させて頂きます。

ローカルにあるファイルを
Googleドライブに保存する機能を実装しています。

今回実現したいことは2つです。

1.複数ファイルをアップロードする
2.複数ファイルを1ファイルに圧縮(まとめられればOK)

1ファイルをGoogleドライブに保存するコード

コード.gs

function doGet(e) { 
  //トップページを読み込む  
  var template = HtmlService.createTemplateFromFile('index.html');
  return template.evaluate();
}

function ProcFileUpload(formObject) {
  // 各種情報を取得
  var wkFolderId = DriveApp.createFolder('TEST').getId();
  var folder = DriveApp.getFolderById(wkFolderId);

  // ファイルを格納
  var drive_file = folder.createFile(formObject.fileUpload);

  return drive_file.getUrl();
}

index.html(JavaScript)

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>

  <body>
  <form id="formUpload">
    <input type="file" name="fileUpload" />
  </form>
  <button id="btnUpload">アップロード</button>

  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
  <script>
    var this_form = document.getElementById("formUpload");
    document.getElementById("btnUpload").addEventListener('click', function() { handleFormUploadSubmit(this_form) });

    function handleFormUploadSubmit(formObject) {
      google.script.run.withSuccessHandler(SuccessMsg).ProcFileUpload(formObject);
    }

    function SuccessMsg(rtnInfo) {
      alert('Success!! '+rtnInfo);
    }

  </script>
  </body>
</html>

試したこと

inputタグでwebkitdirectoryやmultipleを指定しましたが、
コード.gs側でファイルをうまく取り扱えませんでした。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

このような修正は如何でしょうか。toneさんの手法で行う場合を想定して修正してみました。inputでmultipleを使用して複数のファイルをアップロードし、それらをzipで圧縮して1つのファイルとしてGoogle Driveへ保存する流れで動作します。ポイントと感じたところは、HTML側で全てのファイルをオブジェクトとしてまとめてからGAS側へ送るところかと思います。

スクリプトを使用する際の注意点は、下記のGAS側、HTML側のスクリプトを入れ替えた後に新たなバージョンとしてWeb Appsをデプロイしてから実行するところです。これにより変更したスクリプトが反映されます。

GAS側のスクリプト

function ProcFileUpload(obj) {
  var blobs = obj.map(function(e) {
    return Utilities.newBlob(Utilities.base64Decode(e.data), e.mimeType, e.fileName)
  });
  var zip = Utilities.zip(blobs, "sample.zip"); // zipのファイル名を変更する場合はここを変更してください。

  // 各種情報を取得
  var folder = DriveApp.createFolder('TEST');

  // ファイルを格納
  var drive_file = folder.createFile(zip);

  return drive_file.getUrl();
}

HTML側のスクリプト

<input name="fileUpload" id="files" type="file" multiple>
<button id="btnUpload" onclick='getFiles()'>アップロード</button>

<script>
function getFiles() {
  const f = document.getElementById('files');
  const r = Promise.all([...f.files].map((file, i) => {
    const fr = new FileReader();
    return new Promise((r) => {
      fr.onload = (e) => {
        const data = e.target.result.split(",");
        return r({fileName: f.files[i].name, mimeType: data[0].match(/:(\w.+);/)[1], data: data[1]});
      }
      fr.readAsDataURL(file);
    });
  }));
  r.then((obj) => {
    google.script.run.withSuccessHandler((id) => {
      console.log(id);
    }).ProcFileUpload(obj);
  });
}
</script>

注意点

この方法では注意すべき点が御座います。

  1. HTML側からGAS側へ送ることのできるデータのサイズは50 MB程度です。(程度としているのはデータを送る際に他の情報が含まれるためか、50 MBよりも若干小さいためこのような表現にしています。)
  • 今の場合はbase64で変換した後のサイズを指していますのでご注意ください。
  1. Clas DriveAppを使用してGoogle Driveへファイルを作成する際のBlobの最大サイズは50 MBです。
  • 今の場合、zip圧縮前のBlobサイズの最大値が50 MBです。
  1. この方法ではファイルサイズが10 MB程度でもアップロードしてファイルとして保存されるのに20-30秒程度と結構な時間を要しますので大きなサイズのファイルをやり取りする場合はこれを考慮してください。

Google Drive上でファイルをzipで圧縮するにはGASが必要ですが、ファイルをアップロードするだけであればDrive APIを使用する方が効率が良いように思われます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/26 13:00

    kisojinさん、前回に引き続き今回もありがとうございます。
    注意点なども細かく記載して頂けるのは嬉しいです。
    現在いろいろ試して動かそうとしているのですが動作しません・・・
    Googleの拡張サービスなどで何かAPI等を有効にする必要があるのでしょうか?
    (Chrome上でソースを編集していて、APIはすべて無効になっている状態です)

    キャンセル

  • 2018/12/26 17:36

    こちらでは動作確認を行った後に回答として提案しているのですが、動作しないとのことで誠に申し訳ございません。まず下記をご確認ください。

    1. 質問内のスクリプトや私の回答内のスクリプトではGoogleの拡張サービスは使用していません。また、マニフェストでスコープを固定していない限り、スクリプトエディタのスコープ自動検出によってスクリプトを動作するために必要なスコープが自動で設定され、「アプリケーションにアクセスできるユーザー:」をそれぞれ「自分」としてWeb Appsをデプロイしているのであれば、デプロイ時に認証することになるかと思われます。Web Appsのデプロイ時に認証しているかどうかご確認ください。
    2. 回答のスクリプトを正しくスクリプトエディタへコピーペーストできているか再度ご確認ください。回答内の「GAS側のスクリプト」、「HTML側のスクリプト」はそれぞれスクリプトファイル、HTMLファイルとして用意しています。
    3. 質問内にあるスクリプトを見ますと、Web Appsをデプロイしてそこへアクセスしてスクリプトを実行していると理解しています。もしもこれが間違っているようですとご指摘ください。Web Appsを使ってスクリプトを使用していると仮定した場合、回答に記載したようにスクリプトを変更した際は新たなバージョンとして再デプロイしてから実行してください。
    4. Web Appsのデプロイ条件をご確認ください。もしも制限をしているようですと、スクリプトの動作テストとして、「次のユーザーとしてアプリケーションを実行:」、「アプリケーションにアクセスできるユーザー:」をそれぞれ「自分」、「全員(匿名ユーザを含む)」として試してみてください。

    上記を確認した後にまだ動作しないようですと、可能であれば動作しない内容について追加情報を頂けないでしょうか。残念ながら私の今の能力では「現在いろいろ試して動かそうとしているのですが動作しません・・・」だけでは動作しないという状況のみの理解に留まります。これについては私の力不足で申し訳ありません。

    どのようにスクリプトを実行しようとしているのか、実行した際のスクリプトの動作状況、エラーなどの情報を頂けますと問題点を見つけるための助けになると思います。また、質問内や回答内にあるスクリプト以外のスクリプトが問題になっている場合は問題点の推測がより困難になるかと思われます。

    ところで、「Chrome上でソースを編集していて、APIはすべて無効になっている状態です」の意味が分かりません。これについてお教えいただけないでしょうか。

    キャンセル

  • 2019/01/07 12:02

    kisojinさん、ご返信ありがとうございます。
    お返事が遅くなってしまい、申し訳ありませんでした。

    動作しなかった原因がわかりました。
    ご回答いただいたソースに問題はなく、私が使用していたファイルに問題がありました。

    3つのテキストファイルをアップロードしようとしていましたが、
    3ファイルとも文字の記述がなく内容がなかったため、うまく動作しなかったようです。
    中に文字を記述して保存したテキストファイルを使用したところ、動作しました。

    ご質問頂いた件ですが、私の環境をお伝えしようとしていました。
    Chrome上でG Suite Developer Hubを開き、スクリプトエディタを起動して開発をしており、
    開発環境のAPIはすべて無効になっています。
    Drive APIなど、なにかAPIを有効にしないと動作しないのかと思いまして。。。

    わかりにくい文章になってしまい申し訳ありませんでした。

    キャンセル

  • 2019/01/09 11:03

    ご返事頂き有難うございます。無事動作したとのこと、ご連絡有難うございます。安心しました。

    キャンセル

0

できてるみたいだし、本筋がからそれるのですがコメントとして

やろうとしていることからすると、google drive file streamに普通にコピペ(もしくは、batchで動作可能なzipソフトを使ってbatch処理)をしたほうが楽で早いように思います

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る