LANG SELRCT

Google Apps Scriptのコードを書く場所  (新規作成: スプレッドシート | スクリプトエディタ

2021年10月20日水曜日

GASでWebアプリを作ってローカルファイルをGoogleドライブにアップしたい(アプリを開くユーザーとファイルをアップロードするユーザーを分けたい)



GASでWebアプリを作ってローカルファイルをGoogleドライブにアップしたい

以下の条件を満たすもの

条件
  1. アップロード先はGoogleドライブの共有フォルダ
  2. そのフォルダには権限が設定されている
  3. Webアプリを開いたユーザーはそのフォルダにアクセスする権限がない
  4. アップロード後、3のユーザにアップロードしたファイルだけ閲覧権限を付与する

というニッチな条件を満たすために考えました。


条件3をどうするか
「Webアプリを開いたユーザーはそのフォルダにアクセスする権限がない」

権限がないので、ファイルをアップロードする直前に権限を付与する?
  • 閲覧権限だけだとアップロードできないので編集権限も必要
  • フォルダへの編集権限を付与すると、フォルダ内にある他のファイルも閲覧、編集できる
  • そうなると4を満たせない


そこで考えた方法
「フォルダの編集権限を持ったユーザーが代わりにファイルをアップロードする」

Webアプリを開いたユーザーとは別のAdminユーザにやってもらう。
もう一つGASのプロジェクトを作るとできそう。

どうやるか考えてみる。
  1. ファイルをアップロードする処理は別のアプリを作って実行する
  2. それをライブラリとして扱う
  3. ライブラリ側アプリの実行ユーザーはアップロード先フォルダの編集権限を持っている
これでできそう。



そして書いたコード


画面を操作する側のGASプロジェクト


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

function upload_file_gs(reader_result, file_name) {
  var email = "追加したいメールアドレス";
  var file_url = FileUpload.run(reader_result, file_name, email)
  return file_url;
}



index.html
<!DOCTYPE html>
<html>
<body>
  <form>
    <div>
      <input type="file" id="my_files" multiple>
    </div>
  </form>
  <textarea id="upload_file_ta" class="display_none"></textarea>
  <label id="upload_label"></label>
  <div id="upload_div"></div>
  <script>
    document.getElementById("my_files").addEventListener("change", 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 = "アップロードしています...";
      }
    }

    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 = "アップロードしました";
      }
    }

    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>



ライブラリ側のGASプロジェクト


コード.gs
var FOLDER_ID = "保存先フォルダのID";
function run(reader_result, file_name, email) {
  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();
  drive_file.addViewer(email);
  return file_url;
}



関連記事


index.htmlはこれと同じです。
Google Driveに複数ファイルをアップロードしたい(submitボタン使わない)


GASのライブラリの扱いは別途書き残しました。
Google Apps Scriptでライブラリを作って使う

最新の投稿

GASでWebアプリを作ってローカルファイルをGoogleドライブにアップしたい(アプリを開くユーザーとファイルをアップロードするユーザーを分けたい)

Google Driveに複数ファイルをアップロードしたい(submitボタン使わない) の応用です。 GASでWebアプリを作ってローカルファイルをGoogleドライブにアップしたい 以下の条件を満たすもの 条件 アップロード先はGoogleドライブの共有フォルダ そのフォルダ...