星期一, 11月 10, 2025

[GAS] LineBot 取得圖檔並儲存至 Goolge Drive

Line 有提供 content API 可以取得使用者傳送的圖檔 (Images)、影片 (videos)、音檔 (audio) 和檔案 (files),該筆記會以傳送 jpeg 圖檔 (Images) 為主

content API
https://api-data.line.me/v2/bot/message/{messageId}/content

Response

status code 返回 200 且 content 是 blob,該 blob 會自動被刪除,官方並不保證會留存多久


Error response

呼叫後的 status code 有 404 和 410
  • 404:不存在的 messageID
  • 410:使用者並沒有傳送訊息 (message)
// 404 Not Found json
{
  "message": "not found"
}

// 410 Gone json
{
  "message": "The content is gone"
}

Google Apps Script .gs Code
function doPost(e) {
  try {
    let contents = JSON.parse(e.postData.contents);
    let event = contents.events[0];

    if (event.type === 'message' && 
        event.message &&
        event.message.type === 'image') {

      let messageId = event.message.id;

      let imageBlob = downloadLineImage(messageId);

      if (imageBlob) {
        let folderName = 'LineBot_Images';
        saveBlobToDrive(imageBlob, folderName);
      }
    }

  } catch (e) {
    WriteLog([new Date(), "錯誤訊息:", e.toString()]);
  }
}

function downloadLineImage(messageId) {

  let lineChannelAccessToken = getProperties("LineChannelAccessToken");

  let url = `https://api-data.line.me/v2/bot/message/${messageId}/content`;

  let options = {
    'headers': {
      'Authorization': 'Bearer ' + lineChannelAccessToken,
    },
    'method': 'get',
    'muteHttpExceptions': true,
  };

  try {
    let response = UrlFetchApp.fetch(url, options);
    return response.getBlob();
  } catch (e) {
    WriteLog([new Date(), "錯誤訊息:", "下載 Line 圖片錯誤:" + e.toString()]);
    return null;
  }
}

function saveBlobToDrive(blob, folderName) {

  try {
    // 尋找或建立目標資料夾
    let folder = DriveApp.getFoldersByName(folderName);
    if (folder.hasNext()) {
      folder = folder.next();
    } else {
      folder = DriveApp.createFolder(folderName);
    }

    // 設定檔案名稱 (例如: LineImage_20251028_100000.jpg)
    let timestamp = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'yyyyMMdd_HHmmss');

    // 範例:blob.getContentType() 回傳 image/jpeg
    let fileName = `LineImage_${timestamp}.${blob.getContentType().split('/').pop()}`;

    // 儲存檔案
    folder.createFile(blob.setName(fileName));
    WriteLog([new Date(), `檔案已儲存到 Drive:${fileName}`]);

  } catch (e) {
    WriteLog([new Date(), "儲存到 Google Drive 錯誤:" + e.toString()]);
  }
}

測試結果

沒有留言:

張貼留言