影片S3 presigned url前端S3 的 Bucketindex.html<!DOCTYPE html>
<html lang="zh-TW">
<head>
  <meta charset="UTF-8">
  <title>影片上傳平台</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="upload-container">
    <h2>上傳影片</h2>
    <form id="uploadForm">
      <input type="file" id="fileInput" accept="video/*" required><br>
      <button type="submit">開始上傳</button>
    </form>
    <div class="status" id="status"></div>
  </div>
  <script src="script.js"></script>
</body>
</html>
style.cssbody {
  font-family: Arial, sans-serif;
  background: linear-gradient(135deg, #eef2f3, #8e9eab);
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0;
}
.upload-container {
  background: #fff;
  padding: 2rem;
  border-radius: 12px;
  box-shadow: 0 8px 20px rgba(0,0,0,0.15);
  width: 400px;
  text-align: center;
}
h2 {
  margin-bottom: 1rem;
  color: #333;
}
input[type="file"] {
  margin: 1rem 0;
  padding: 0.5rem;
}
button {
  background-color: #4CAF50;
  color: white;
  padding: 0.75rem 1.5rem;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 1rem;
  transition: 0.3s;
}
button:hover {
  background-color: #45a049;
}
.status {
  margin-top: 1rem;
  color: #555;
}
script.jsconst form = document.getElementById('uploadForm');
const fileInput = document.getElementById('fileInput');
const statusDiv = document.getElementById('status');
form.addEventListener('submit', async (e) => {
  e.preventDefault();
  const file = fileInput.files[0];
  if (!file) {
    statusDiv.textContent = "請先選擇影片!";
    return;
  }
  statusDiv.textContent = "正在請求上傳網址...";
  try {
    // ⚠️ 請換成你的 API Gateway endpoint
    const res = await fetch("https://iwlw3i3ys4.execute-api.ap-northeast-1.amazonaws.com/prod/generate-url", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ filename: file.name })
    });
    const data = await res.json();
    const uploadUrl = data.url;
    statusDiv.textContent = "正在上傳影片...";
    // PUT 檔案到 S3 (Presigned URL)
    await fetch(uploadUrl, {
      method: "PUT",
      body: file
    });
    statusDiv.textContent = "✅ 上傳完成!";
  } catch (err) {
    console.error(err);
    statusDiv.textContent = "❌ 上傳失敗,請稍後再試";
  }
});
 
import json
import boto3
import base64
import os
s3 = boto3.client("s3")
BUCKET_NAME = os.environ.get("BUCKET_NAME", "my-upload-bucket")
def lambda_handler(event, context):
    try:
        # API Gateway 預設會把 binary 轉成 base64
        file_content = base64.b64decode(event["body"])
        # 從 query string 或 header 取檔名
        filename = event.get("queryStringParameters", {}).get("filename", "upload.bin")
        # 上傳到 S3
        s3.put_object(
            Bucket=BUCKET_NAME,
            Key=filename,
            Body=file_content,
            ContentType="video/mp4"  # 可依需求調整
        )
        return {
            "statusCode": 200,
            "headers": {
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Methods": "OPTIONS,POST",
                "Access-Control-Allow-Headers": "Content-Type"
            },
            "body": json.dumps({"message": f"檔案 {filename} 已上傳成功"})
        }
    except Exception as e:
        return {
            "statusCode": 500,
            "body": json.dumps({"error": str(e)})
        }
}
```
4. 改完之後要將 Lambda 新版本 Deploy 上去...見上圖右上角的下拉選單...
5. 從 http://exsky-vlog-web.s3-website-ap-northeast-1.amazonaws.com/ 這個網址去取用 S3 Bucket 的靜態網頁、上傳頁面
6. 觀看上傳結果