前面發行 Pre-Signed URL 需要透過 裝有 AWS CLI 且 安置了 Key 的主機進行,這顯然會阻礙使用上的方便性。 我們接著來做一個 API Server 來接收請求,並且觸發指令,拿回 URL 後,回傳給使用者吧!
from flask import Flask, request, jsonify
import boto3
import os
app = Flask(__name__)
# AWS 設定(建議用 IAM Role 或環境變數,不要硬編 key)
AWS_ACCESS_KEY = os.getenv("AWS_ACCESS_KEY_ID")
AWS_SECRET_KEY = os.getenv("AWS_SECRET_ACCESS_KEY")
AWS_REGION = "ap-northeast-1"
S3_BUCKET = "your-bucket-name"
s3_client = boto3.client(
"s3",
region_name=AWS_REGION,
aws_access_key_id=AWS_ACCESS_KEY,
aws_secret_access_key=AWS_SECRET_KEY
)
@app.route("/generate_presigned_url", methods=["POST"])
def generate_presigned_url():
data = request.get_json()
file_name = data.get("file_name")
file_type = data.get("file_type", "application/octet-stream")
if not file_name:
return jsonify({"error": "file_name is required"}), 400
try:
presigned_url = s3_client.generate_presigned_url(
"put_object",
Params={
"Bucket": S3_BUCKET,
"Key": f"uploads/{file_name}",
"ContentType": file_type
},
ExpiresIn=3600 # URL 有效期 (秒)
)
return jsonify({"url": presigned_url})
except Exception as e:
return jsonify({"error": str(e)}), 500
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=True)
exsky-backup-media
AWS_ACCESS_KEY = os.getenv("AWS_ACCESS_KEY_ID")
AWS_SECRET_KEY = os.getenv("AWS_SECRET_ACCESS_KEY")
AWS_REGION = "ap-northeast-1"
S3_BUCKET = "exsky-backup-media"
s3_client = boto3.client(
"s3",
region_name=AWS_REGION,
aws_access_key_id=AWS_ACCESS_KEY,
aws_secret_access_key=AWS_SECRET_KEY
)
/generate_presigned_url
路徑時,以 POST 請求輸入參數s3_client.generate_presigned_url
去生成 URL@app.route("/generate_presigned_url", methods=["POST"])
def generate_presigned_url():
data = request.get_json()
file_name = data.get("file_name")
file_type = data.get("file_type", "application/octet-stream")
if not file_name:
return jsonify({"error": "file_name is required"}), 400
try:
presigned_url = s3_client.generate_presigned_url(
"put_object",
Params={
"Bucket": S3_BUCKET,
"Key": f"uploads/{file_name}",
"ContentType": file_type
},
ExpiresIn=3600 # URL 有效期 (秒)
)
return jsonify({"url": presigned_url})
except Exception as e:
return jsonify({"error": str(e)}), 500
python xxx.py
執行起來時,運作 app.run 這行,將伺服器開在指定的 portif __name__ == "__main__":
app.run(host="0.0.0.0", port=8087, debug=True)
密鑰放在系統變數,可能會被幹走,有一點點風險
這個看起來不錯,但是 Amazon Lambda Function 最長只能連續執行 15 分鐘