Backend Cookbook 1: Uploading AWS S3 Objects Using Presigned URLs

Yes Lee
6 min readJun 9, 2019

--

Nice coffee from Hulu House, where I wrote this story.

上傳照片或檔案是應用程式中基本的功能之一,如果後端是用 Firebase 類的服務的話那是有現成的 API 和 Storage 可以用,但如果要自己從頭做起的話 AWS S3 就是一個常見的選擇,而透過 presigned url 上傳是其中一種方式。

Requirement

  1. Create an AWS S3 presigned URL
  2. Upload an image through the URL

1. Prerequisite

Create presigned URL 其實並不需要 permission,是在使用 URL 的時候才會被檢查用來 create URL 的 credential 在當下是否有 presigned action 的 permission,不過在這邊我們還是先把需要的 credential、permission 和 resource 都建好。

1–1. Create an IAM user: practices-bc-01

首先我們建立一個 IAM User,不給他任何 permission。

Create a user: practices-bc-01

1-2. Create a policy with required permissions: practices-bc-01

這邊沒有要嘗試 fine tune permissions,所以直接開了個等同於 AmazonS3FullAccess 的 Policy。

Create a policy: practices-bc-01

1-3. Grant the user the permission

為了讓 user 的 credential 有上傳 object 到 S3 的 permission,我們把剛剛 create 的 policy 加到 user 身上。

Grant the user the permission

1-4. Create a S3 bucket: practices-bc-01

最後再 create 一個 S3 bucket 當作照片上傳的地方,bucket 是有分 region 的,記得在這邊選的 region 必須要和 create presigned URL 時用的一樣。

Create a S3 bucket

Bucket 的 permission 也有影響:

  1. Block public access to buckets and objects granted through new access control lists (ACLs) 需要打開,在使用 presigned URL 時才不會 Access Denied。
  2. Block public access to buckets and objects granted through any access control lists (ACLs) 需要打開,上傳照片的 ACL 才能設定為 public-read。
Permission of the bucket
S3 bucket

2. Create the presigned URL

準備好 credential、permission 和 resource 後,我們就可以用 Node.js 和 aws-sdk 來 create presigned URL 了。

// .env
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_REGION=
// src/create-url.js
require("dotenv").config();
const fs = require("fs");
const AWS = require("aws-sdk");
const s3 = new AWS.S3({
apiVersion: "2006-03-01"
});
var params = {
Bucket: "practices-bc-01",
Key: "test.jpg",
ACL: "public-read",
ContentType: "image/jpeg"
};
var url = s3.getSignedUrl("putObject", params);
fs.writeFileSync("src/url.txt", url);
// src/url.txt
https://practices-bc-01.s3.ap-northeast-1.amazonaws.com/test.jpg?AWSAccessKeyId=AKIAXQN5DOMFBQJ3MTWB&Content-Type=image%2Fjpeg&Expires=1560079674&Signature=RVVfTM6OcVp832%2F9%2BujX%2BRss2ZI%3D&x-amz-acl=public-read

3. Upload image through cURL

最後我們用 cURL 將一張 test.jpg 的照片透過 presigned URL 上傳到 S3。

#!/bin/sh
curl -X "PUT" \
-H "Content-Type: image/jpeg" \
-T "$(pwd)/src/test.jpg" \
-L $(cat "$(pwd)/src/url.txt")
Successfully upload a photo to S3

成功!

--

--

Yes Lee
Yes Lee

Written by Yes Lee

Frontend Engineer in Taiwan.

No responses yet