LANG SELRCT

コードを書く場所についてはこちら

2018年1月17日水曜日

Google Driveに複数ファイルをアップロードしたい


Googleドライブの指定したフォルダにファイルをアップロードする
Googleドライブの指定したフォルダにファイルをアップロードする(formのsubmitボタンを使わない)

上記の記事では一度にアップロードできるファイル数はひとつでしたが
同時に複数のファイルをアップロードしたい場合は

multiple を追加して

<input name="myFile" type="file" multiple />

として
コード.gsの方では folder.createFile を folder.createFiles にしたら実現できそうな気がしましたが .createFiles なんてものはありませんでした



ひとつアップロードできたら複数もできるだろうと思っていたらそう簡単にはいかず
ファイル選択ボタンを複数用意したり、ファイル選択の操作を複数回行うことなく
一度の操作で実現したくて色々と調べて試した結果
stackoverflow で回答されているコードにたどり着きました


今回は上記のコードを参考に
やりたいことを実現したコードを書きました


やりたいこと
  1. 「ファイルを選択」をクリックする
  2. ローカルファイルの選択画面が開く
  3. 任意のファイルを複数選択して「開く」をクリックする
  4. 「選択されていません」に選択したファイル数が表示される
  5. 「Submit」をクリックする
  6. 指定したフォルダにファイルがアップロードされる
  7. アップロードしたファイルのURLのリンクが表示される



コード.gs
function doGet() {
  return HtmlService.createHtmlOutputFromFile('index');
}

var FOLDER_ID = "ID";
function upload_file_gs(reader_result, file_name) {
  var result_split = reader_result.split(',');
  var content_type = result_split[0].split(';')[0].replace('data:', '');
  var row_data = result_split[1];
  var data = Utilities.base64Decode(row_data);
  
  var file = Utilities.newBlob(data, content_type, file_name);
  var folder = DriveApp.getFolderById(FOLDER_ID);
  var drive_file = folder.createFile(file);
  var file_url = drive_file.getUrl();
  return file_url;
}
意訳
この処理は以下を実行する
指定したHTMLファイルを表示する


アップロード先のドライブのフォルダID
この機能がやること
受け取ったreader_resultをカンマ(,)で区切って 
content_typeを抜き出して
row_dataを抜き出して
row_dataをbase64Decodeして

Utilities.newBlobにファイルのデータとcontent_typeとファイル名を渡して
Google DriveのフォルダIDを指定して
そこにファイルを作成して
作成したファイルのURLを取得して
返す




index.html
<!DOCTYPE html>
<html>
<body>
  <form>
    <div>
      <input type="file" id="my_files" multiple>
      <button id="bt" type="button">Submit</button>
    </div>
  </form>
  <br>
  <label id="upload_label"></label>
  <div id="upload_div"></div>

  <script>
    document.getElementById("bt").addEventListener('click', upload_files);
    var files_len = 0;
    var uploaded_len = 0;
    
    function upload_files() {
      var files = document.getElementById('my_files').files;
      files_len = files.length;
      for (var i = 0; i < files.length; i++) {
        uploadFile(files[i]);
        document.getElementById('upload_label').textContent = "uploading...";
      }
    }

    function uploadFile(file) {
      var reader = new FileReader();
      reader.onload = function() {
        var reader_result = reader.result;
        var file_name = file.name
        google.script.run
          .withSuccessHandler(uploaded)
          .upload_file_gs(reader_result, file_name);
      }
      reader.readAsDataURL(file);
    }

    function uploaded(file_url) {
      create_link(file_url);
      uploaded_len ++;
      if(uploaded_len == files_len){
      document.getElementById('upload_label').textContent = "uploaded";
      }
    }

    function create_link(file_url) {
      var div = document.getElementById("upload_div");
      var br = document.createElement("br");
      var link = document.createElement("a");
      link.textContent = file_url;
      link.setAttribute("href", file_url);
      link.setAttribute("target", "_blank");
      div.appendChild(link);
      div.appendChild(br);
    }
  </script>
</body>
</html>
意訳
これはHTML5文書です


フォームを置く

ファイルを選択するボタンを置く
アップロードするボタンを置く



テキストエリアを置く
アップロードしたファイルのURLを入れるdivを用意しておく


idがbtの要素がクリックされたらupload_filesを実行する
アップロードするファイル数の初期値を0にしておく
アップロードされたファイル数の初期値を0にしておく

この機能がやること
idがmy_filesの要素のファイルをすべて取得する
アップロードするファイル数をfiles_lenに入れる
ファイルの数だけ以下を繰り返す
uploadFileにファイルを一つずつ渡す
idがupload_labelの要素のテキストをuploading...にする



この機能がやること
FileReaderを作って
読み込みが成功したら以下を実行する
resultを取得して
fileから名前を取得して
.gsファイルの指定したスクリプトを実行する
成功したらuploadedを実行する
実行する.gsファイルはコード.gsにあるupload_file_gsでreader_result, file_nameを渡す

fileを読み込む


この機能がやること
受け取ったfile_urlをcreate_linkに渡す
アップロードしたファイル数を1ずつ足していく
もしアップロードしたファイル数とアップロードするファイル数が一致したら
idがupload_labelの要素のテキストをuploadedにする



この機能がやること
idがupload_divの要素を取得する
改行を作る
ハイパーリンクを作る
リンクのテキストに受け取ったfile_urlを入れる
リンク先にfile_urlを設定する
リンクを新規タブで開くように設定する
upload_divにリンクを追加する
upload_divに改行を追加する






参考

HTML Service: Communicate with Server Functions / Forms
https://developers.google.com/apps-script/guides/html/communication#forms


Uploading Multiple Files to Google Drive with Google App Script
https://stackoverflow.com/questions/31126181/uploading-multiple-files-to-google-drive-with-google-app-script


Keyword
Google Apps Script Google Drive file upload multiple
Goolge Apps Script 複数ファイルアップロード Google Drive