在 Google Apps Script 部署 「一鍵生成 PPTX」 專案

GAS Web App 部署教學

在 Google Apps Script 部署 「一鍵生成 PPTX」 專案

以下內容示範 最少改動 即可將原始 HTML 搬到 GAS Web App,不再被 CSP 或 CORS 擋下。

一、為什麼在 GAS 會被擋?

問題背後機制解法概要
外部 <script> 被攔 Web App 的 CSP 只允許同源腳本 自己當 Proxy: 用 UrlFetchApp 抓 CDN,再以 /exec?lib=xxx 回前端
API Key 寫在瀏覽器端 金鑰外洩 / CORS 預檢失敗 搬到伺服器:google.script.run 讓後端呼叫 AI
base64 圖片太大 部分 sandbox 對 data URI 有限制 可行;若失敗改用後端轉檔

二、四步驟流程

步驟 1|建立檔案結構

📁 專案
 ├─ Code.gs         ← 後端主程式
 ├─ libs.gs         ← CDN 代理 / 快取
 ├─ Index.html      ← 畫面 (移除外部 <script>)
 └─ app.js.html     ← 原本的 JS 內容

步驟 2|後端 Code.gs

function doGet(e){
  if(e.parameter.lib) return proxyLib(e.parameter.lib);
  return HtmlService
    .createTemplateFromFile('Index')
    .evaluate()
    .setSandboxMode(HtmlService.SandboxMode.IFRAME)
    .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}

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

function proxyLib(name){
  const map={reveal:'https://cdn.jsdelivr.net/…/reveal.min.js',…};
  const url=map[name];
  const cache=CacheService.getScriptCache();
  let js=cache.get(url);
  if(!js){js=UrlFetchApp.fetch(url).getContentText();cache.put(url,js,21600);}
  return ContentService.createTextOutput(js).setMimeType(ContentService.MimeType.JAVASCRIPT);
}

並將 AI 呼叫包裝成 aiGenerateSlides()aiGenerateImage() 兩支函式。

步驟 3|前端 Index.html 與 app.js.html

  1. Index.html: 保留結構,將所有 CDN 以 <script src="?lib=reveal"> 方式引用。
  2. app.js.html: 把所有 fetch() 改用 google.script.run 叫後端函式。

步驟 4|部署

  1. 專案設定 → 連線權限 同意 UrlFetch 範圍。
  2. 部署 → 新部署 → Web App:執行身分選「自己」,存取權選「任何擁有連結的人」。
  3. 點「部署」取得 URL,即可使用。

三、常見攔截原因 & 解法

錯誤訊息立刻檢查解法
CSP Refused to load script… <script> 是否仍指外網 確認已改成 ?lib=xxx
UrlFetchApp 403 AI API Key 或配額 Script Properties 更新密鑰
CORS blocked by browser 前端是否還在 fetch x.ai 改用 google.script.run
PPTX 圖片缺失 img 是否 fully loaded await img.complete 後再截圖

四、額外小技巧

  • 單檔≤50 KB: 拆成多個 .html 模板避免大小限制。
  • CDN 快取: CacheService 每 6 小時更新一次即可。
  • 圖片過大: 後端轉 blob → base64,可減少跨域問題。
  • 嵌入 Sites/LMS: 已開 ALLOWALL,可 <iframe> 直接用。

以上就是完整教學,祝部署順利!🎉