iT邦幫忙

2025 iThome 鐵人賽

DAY 6
0

前言

我們前面花了四篇,穿插了 S3 Bucket 如何收取資料。 但是要串預簽上傳網址的時候,會有點麻煩。 所以前一回用 EC2 來架 NginX;這東西要自己維護,還要 24 小時常駐開啟,如果你沒有使用 EC2 的習慣,或者不熟悉建立伺服器,或是你事情很多工作複雜,沒有時間來管理了,那就非常推薦你走 API Gateway + Lambda 的組合,管理會比較輕鬆!!

簡介

API Gateway 顧名思義,就是全託管的 API Server。 而 Lambda Function 就是你可以寫一段程式碼,運行在無伺服器環境中、由 AWS 官方管理的環境中。

實作

  1. 建立可以運行 Python 原始碼的 Lambda Function
  2. 原始碼如下:
import json
import boto3
import os
import urllib.parse

s3 = boto3.client("s3")
BUCKET_NAME = os.environ.get("BUCKET_NAME", "exsky-backup-media")

def lambda_handler(event, context):
    # 解析前端傳來的檔案名稱
    params = json.loads(event['body'])
    filename = params.get("filename")

    if not filename:
        return {
            "statusCode": 400,
            "body": json.dumps({"error": "Missing filename"})
        }

    key = urllib.parse.quote(filename)
    
    # 產生預簽名 URL(有效 10 分鐘)
    presigned_url = s3.generate_presigned_url(
        'put_object',
        Params={'Bucket': BUCKET_NAME, 'Key': key},
        ExpiresIn=600  # 10 分鐘 = 600 秒
    )

    return {
        "statusCode": 200,
        "body": json.dumps({"url": presigned_url})
    }

  • BUCKET_NAME = os.environ.get("BUCKET_NAME", "exsky-backup-media") 這句是去抓環境變數 BUCKET_NAME 的值,如果抓不到,那回傳預設值 "exsky-backup-media"
  1. 建立 API Gateway HTTP API
    • HTTP API
    • 建立 /generate-url 路由,綁定 POST 方法
    • 整合方式選「Lambda 函數」
    • 勾選「啟用 CORS」/ 要改 S3 Bucket 的設定
    [
      {
        "AllowedHeaders": ["*"],
        "AllowedMethods": ["PUT"],
        "AllowedOrigins": ["*"],
        "ExposeHeaders": [],
        "MaxAgeSeconds": 3000
      }
    ]
    
  2. 設定 Role for Lambda Function
    {
      "Effect": "Allow",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::exsky-backup-media/*"
    }
    
  3. 前端原始碼加入
    const filename = "hello.jpg";
    const response = await fetch("/generate-url", {
      method: "POST",
      body: JSON.stringify({ filename }),
    });
    const { url } = await response.json();
    
    await fetch(url, {
      method: "PUT",
      body: file, // File object from <input type="file">
    });
    

結論

  • 還缺少前端畫面,下回分曉

上一篇
【Day 5】 自己做 API Server 發行 Pre-Signed URL
下一篇
【Day 7】 用 Amazon S3 架靜態網站
系列文
無法成為片師也想拍 Vlog?!個人影音小工具的誕生!10
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言