📦 ทำ File Upload Service ด้วย S3 + Lambda + API Gateway พร้อม Presigned URL

Sharing is caring!

บทนำ

หนึ่งในงานยอดนิยมบน AWS คือการสร้าง File Upload Service ที่ให้ผู้ใช้สามารถอัปโหลดไฟล์ขึ้น Amazon S3 ได้โดยตรง โดยไม่ต้องผ่านเซิร์ฟเวอร์ของเรา (ลดค่าใช้จ่าย และเพิ่มความปลอดภัย)

ในบทความนี้ เราจะมาดูขั้นตอนการสร้างระบบอัปโหลดไฟล์แบบครบวงจร ด้วย API Gateway + AWS Lambda + S3 พร้อมใช้ Presigned URL เพื่อให้อัปโหลดได้โดยตรงจาก Frontend

1. สถาปัตยกรรมระบบ

สถาปัตยกรรมโดยรวมของระบบนี้ประกอบด้วย 4 ส่วนหลัก:

  • Frontend (React / Angular) – ใช้เรียก API เพื่อขอ Presigned URL
  • API Gateway – ทำหน้าที่เป็น Gateway รับ Request
  • Lambda Function – สร้าง Presigned URL ผ่าน AWS SDK
  • Amazon S3 – ที่เก็บไฟล์หลังอัปโหลดสำเร็จ

2. สร้าง S3 Bucket สำหรับเก็บไฟล์

เริ่มต้นด้วยการสร้าง S3 Bucket สำหรับเก็บไฟล์ที่อัปโหลด:

aws s3api create-bucket --bucket my-upload-bucket --region ap-southeast-1
    

จากนั้นตั้งค่า Policy ให้ Lambda สามารถเขียนไฟล์ได้:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:PutObject", "s3:GetObject"],
      "Resource": "arn:aws:s3:::my-upload-bucket/*"
    }
  ]
}
    

3. เขียน Lambda สำหรับสร้าง Presigned URL

โค้ดด้านล่างนี้คือ Lambda Function ที่จะสร้าง Presigned URL สำหรับให้ Frontend ใช้อัปโหลดไฟล์โดยตรงไปยัง S3:

// index.js
const AWS = require('aws-sdk');
const s3 = new AWS.S3();

exports.handler = async (event) => {
  const body = JSON.parse(event.body);
  const fileName = body.fileName;
  const fileType = body.fileType;

  const params = {
    Bucket: 'my-upload-bucket',
    Key: fileName,
    ContentType: fileType,
    Expires: 60 // URL ใช้ได้ 1 นาที
  };

  const uploadURL = await s3.getSignedUrlPromise('putObject', params);

  return {
    statusCode: 200,
    headers: { "Access-Control-Allow-Origin": "*" },
    body: JSON.stringify({ uploadURL })
  };
};
    

4. ตั้งค่า API Gateway เพื่อเรียก Lambda

สร้าง API Gateway แบบ HTTP API แล้วเชื่อมกับ Lambda Function ที่สร้างไว้ในขั้นตอนก่อนหน้า โดยตั้งค่า Endpoint เช่น:

  • POST /generate-presigned-url → Lambda ที่สร้าง URL

5. ตัวอย่าง Frontend เรียกใช้งาน Presigned URL (React)

ตัวอย่างโค้ด React สำหรับอัปโหลดไฟล์ไปยัง S3 ผ่าน Presigned URL:

// UploadFile.js
import React, { useState } from "react";

function UploadFile() {
  const [file, setFile] = useState(null);

  async function handleUpload() {
    const res = await fetch("https://your-api-id.execute-api.ap-southeast-1.amazonaws.com/prod/generate-presigned-url", {
      method: "POST",
      body: JSON.stringify({ fileName: file.name, fileType: file.type })
    });
    const { uploadURL } = await res.json();

    await fetch(uploadURL, {
      method: "PUT",
      body: file
    });

    alert("อัปโหลดสำเร็จ!");
  }

  return (
     setFile(e.target.files[0])} />
      อัปโหลดไฟล์
  );
}

export default UploadFile;
    

6. ทดสอบการอัปโหลด

เมื่อรัน React App แล้วเลือกไฟล์ → ระบบจะเรียก API Gateway เพื่อขอ URL จากนั้นจะอัปโหลดไปที่ S3 โดยตรงโดยไม่ผ่าน Backend อีกที

คุณสามารถตรวจสอบไฟล์ใน S3 ได้โดยเข้าไปที่:

aws s3 ls s3://my-upload-bucket/
    

7. เสริมความปลอดภัยด้วย CORS และ IAM Policy

เพื่อความปลอดภัย ควรเปิดใช้ CORS เฉพาะโดเมนที่อนุญาตเท่านั้น และจำกัดสิทธิ์ของ Lambda ให้สามารถสร้าง URL ได้เฉพาะ Bucket ที่ระบุ

8. สรุปภาพรวมระบบ Upload Service

เมื่อเชื่อมต่อทุกส่วน เราจะได้ระบบ Upload ที่สมบูรณ์:

  • Frontend → ขอ Presigned URL
  • API Gateway → เรียก Lambda
  • Lambda → สร้าง URL ผ่าน S3 SDK
  • ผู้ใช้ → Upload ไฟล์ตรงไปยัง S3

📘 บทความโดย King Pool

ภาพประกอบ: S3, Lambda, API Gateway, Presigned URL, Upload Flow

อ่านต่อ: การสร้าง REST API ด้วย Lambda + API Gateway + DynamoDB

Leave a Reply

อีเมลของคุณจะไม่แสดงให้คนอื่นเห็น ช่องข้อมูลจำเป็นถูกทำเครื่องหมาย *