星期五, 12月 19, 2025

[GAS] 上傳檔案至 Google Drive

在官方文件 在 HTML 服務:與伺服器函式通訊 - 表單 上有特別提到,當把 html 上的 form 當成參數傳遞至 gs code 內的函數時,form 會變成一個 key-value object,form field names 為 key、form field values 為 value,值會轉成 string,只有 file 會轉成 blob,該筆記紀錄該 GAS 特色功能

index.html
<!DOCTYPE html>
<html>

<head>
  <base target="_top">
  <?!= include('css') ?>
</head>

<body>

  <div class="app-container">
    <form onsubmit="handleFormSubmit(event)">

      <label class="field-label">電子郵件:</label>
      <input type="email" name="userEmail" class="input-field" placeholder="example@mail.com" required>

      <label class="field-label">選擇檔案:</label>
      <input type="file" name="myFile" class="input-field" required>

      <button type="submit" class="btn-submit">上傳</button>
    </form>

    <div class="result-message">等待操作</div>
  </div>

  <script>
    function onSuccessHandler(response) {
        const display = document.querySelector('.result-message');
        display.innerText = "【成功】\n" + response;
        display.className = "result-message text-success";
    }

    function onFailureHandler(error) {
        const display = document.querySelector('.result-message');
        display.innerText = "【失敗】\n" + error.message;
        display.className = "result-message text-failure";
    }

    function handleFormSubmit(event) {

        // 避免 form onsubmit 預設 redirect 行為
        event.preventDefault(); 

        // 取得 form
        let formObject = event.target;
        
        let display = document.querySelector('.result-message');    
        display.innerText = "正在上傳至 Google Drive";
        display.className = "result-message";

        // 呼叫 gs Code 內的 processForm() 並把 form 當成參數
        google.script.run 
          .withSuccessHandler(onSuccessHandler)
          .withFailureHandler(onFailureHandler)
          .processForm(formObject);
    }

  </script>
</body>

</html>

css.html
<style>
  .app-container {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    padding: 30px;
    line-height: 1.6;
  }

  .field-label {
    display: block;
    margin-bottom: 5px;
    font-weight: bold; 
  }

  .input-field {
    width: 280px;
    padding: 8px;
    margin-bottom: 15px;
    border: 1px solid #ccc; 
    border-radius: 4px;
    display: block;
  }

  .btn-submit {
    display: block;
    padding: 8px 20px;
    background-color: #007bff;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
  }

  .btn-submit:hover {
    background-color: #0056b3;
  }

  .result-message {
    margin-top: 20px;
    padding: 15px; 
    border-left: 5px solid #eee;
    background-color: #f9f9f9;
    white-space: pre-wrap;
  }

  .text-success {
    border-left-color: #28a745;
    color: #155724;
  }

  .text-failure {
    border-left-color: #dc3545;
    color: #721c24;
  }
</style>

gs code
function doGet() {
  return HtmlService.createTemplateFromFile('index')
    .evaluate()
    .setTitle('[GAS] 上傳檔案至 Google Drive');
}

function include(fileName) {
  return HtmlService.createHtmlOutputFromFile(fileName).getContent();
}

/**
 * 處理表單提交
 */
function processForm(formObject) {

  try {
    
    let parentFoldID = getFoldID();
    let parentFolder = DriveApp.getFolderById(parentFoldID);

    // 建立時間戳記子資料夾
    let timestamp = Utilities.formatDate(new Date(), "GMT+8", "yyyyMMdd_HHmmss");
    let subFolder = parentFolder.createFolder(timestamp);

    // 儲存檔案 (formObject.myFile 會自動被 GAS 轉為 Blob)
    let fileBlob = formObject.myFile; 
    let file = subFolder.createFile(fileBlob);
    file.setDescription("上傳者:" + formObject.userEmail)

    let message = `
      上傳時間:${timestamp}
      Email:${formObject.userEmail}
      上傳檔案 URL:${file.getUrl()}`;

    return message;

  } catch (error) {

    throw new Error("系統錯誤:" + error.toString());

  }

}

執行結果

沒有留言:

張貼留言