這是 pre-signed URL 學習路線圖的 Level 2,只鎖一件事:同樣一條「先簽好名的網址」,到底是給人下載、還是給人上傳? Level 1 已經把「它是什麼、為什麼點了就能存取私有檔卻不用登入、它是 bearer token、權限不超過產生者、產生時純本機運算」講透了——那些這篇不重講,只在需要時一句話帶過。
這一站的目標很具體:讀完你要能面對兩個真實需求——「使用者要上傳大頭照」和「產一條 24 小時有效的下載連結」——立刻說出各該用 GET 還是 PUT,以及檔案實際上是怎麼流動的。
Level 1 的一句話心智模型(幫你接上):pre-signed URL 就是「一個先簽好名、整包壓進網址裡的 HTTP 請求」。既然它本質是「一個 HTTP 請求」,那這個請求用的是哪個 method(method=HTTP 請求的「動作類別」,白話就是這條網址要「拿」還是「放」;GET / PUT / HEAD),就決定了拿到網址的人能做什麼。這一站就是在講這件事。
這幾題就是本文重點,也是讀完你該能用自己的話答出來的問題。先想想現在答不答得出來,帶著它們往下讀,讀完再回來對照。
GET 跟是 PUT,分別讓拿到網址的人能做什麼?看答案收合GET=讓對方下載這個物件;PUT=讓對方把一個檔案上傳到指定 key(key=檔案在 bucket 裡的路徑+檔名,如 avatars/user-123.jpg)。
GET for downloading,PUT for uploading,HEAD for reading object metadata。(沒開版本控管時;版本控管=S3 幫你保留舊版本,這裡先當沒開)S3 直接用新檔覆蓋掉舊檔——不問你、不報錯、不另存。
presigned HEAD=只讀 metadata(檔案的描述資訊:多大、是圖片還是 PDF 之類),不回檔案內容。
HEAD 的特性就是「只回 header(檔案的基本資訊欄位)、不回 body(檔案內容本身)」。別讓後端(=你自己的伺服器;前端=使用者的瀏覽器/網頁)當「二傳手」(=中轉/搬運工)去扛大檔的流量、CPU 和記憶體。
四步:① 前端跟後端要一條上傳網址 → ② 後端用憑證產一條 presigned PUT URL(純本機、不連 S3)→ ③ 後端回傳這條 URL → ④ 瀏覽器拿它直接 PUT 檔案上 S3。
到期前可重複使用很多次,不是一次性。
上傳大頭照=PUT:前端要 URL → 後端產 presigned PUT URL(指定 key)回傳 → 瀏覽器直接 PUT 照片上 S3;撞名會覆蓋舊照(正合需求)。
24 小時下載連結=GET:後端產一條有效期 24 小時的 presigned GET URL → 給對方 → 對方直接跟 S3 下載;期間可被重複點、多人用,故是秘密。
能答成這樣,這一站就過關了。
先給結論:你在簽 URL 的時候就決定了它是哪一種,靠的就是那個 HTTP method。AWS S3 官方文件把這件事講得很直白——建立 pre-signed URL 時,你要指定「一個 HTTP method」,並且列明:
GETfor downloading objects,PUTfor uploading,HEADfor reading object metadata
翻成白話,同樣一套「先簽好名的網址」機制,換個 method 就變成三種完全不同的用途:
avatars/user-123.jpg)」的連結。對方拿這條就能上傳,完全不用有任何 AWS 帳密或權限(AWS 原話:allows an upload without requiring another party to have AWS security credentials or permissions)。HEAD 這個 method 的特性是「只回 header(檔案的基本資訊欄位)、不回 body(檔案內容本身)」——所以 presigned HEAD 讓對方能查這個物件的描述資訊(這檔多大、是圖片還是 PDF 之類),但不會把檔案內容傳回去。想「先問一下這檔多大、是什麼類型,再決定要不要下載」時很好用。小提醒:這三種的差別只在 method,簽章那套底層機制(把請求算成X-Amz-Signature)三種是同一套。至於那段簽章到底怎麼算出來的、URL 裡那堆X-Amz-*各是什麼——那是 Level 3(SigV4) 的黑箱,這站先不拆,你只要記得「method 決定用途」。
這點很容易踩雷,特別記一下。presigned PUT 綁的是一個指定的 key(可以想成「檔案在 bucket 裡的完整路徑+檔名」,例如 avatars/user-123.jpg)。如果對方上傳時,那個 key 在 bucket 裡已經有一個檔案了,S3 官方文件寫得很清楚:
If an object with the same key already exists in the bucket as specified in the presigned URL, Amazon S3 replaces the existing object with the uploaded object.
也就是說,在沒開版本控管(versioning)的 bucket 上,S3 直接用新檔覆蓋掉舊檔,不會問你、不會報錯、不會另存新檔。這在「大頭照」這種場景其實正合你意——同一個使用者換頭貼,就是要蓋掉舊的。但如果你不想被蓋,就得在產 URL 時給不同的 key(例如帶上時間戳或亂數)。
還有一個容易誤會的點:單純的 presigned PUT 不能限制對方上傳的檔案大小,它只綁「method + key +(可選的)某些 header」。真的要卡大小上限、限副檔名,那是另一種工具(presigned POST policy),屬於後面站的黑箱,這裡先知道「純 PUT 卡不住大小」就好。
你可能會想:上傳檔案我很熟啊——前端把檔案 POST 給我後端,後端再存進 S3,不就好了?為什麼要多搞一條 presigned PUT?
答案是:別讓你的後端當「二傳手」。 想像一個畫面——一百個使用者同時傳大頭照,如果每個檔案都要「先流過你的後端伺服器、再由後端轉存到 S3」,那你的伺服器就得全程扛著這些檔案的流量、CPU 和記憶體,只為了做一件搬運工的事。AWS 官方部落格直接點出這個痛:
Media uploads are typically large, so transferring these can represent a large share of network I/O and server CPU time.
而讓前端(呼叫端)直接傳到 S3 的好處是:
By directly uploading these files to Amazon S3, you can avoid proxying these requests through your application server. This can significantly reduce network traffic and server CPU usage.
尤其是流量會突然暴衝的場景(例如活動一開放、大家同時上傳),二傳手模式逼你為了扛上傳去擴充伺服器;直傳則讓後端在尖峰時能專心處理別的請求(enable your application server to handle other requests during busy periods)。
一句話總結動機:檔案的重活交給 S3 扛(它本來就為海量物件而生),你的後端只負責「發一張限時通行證」這種輕活。
把上面的動機落成具體步驟,這就是過關必背的那張圖。以「使用者在網頁上傳大頭照」為例:
sequenceDiagram participant B as 瀏覽器(前端) participant S as 你的後端 participant O as S3 / MinIO B->>S: 1. 我要上傳大頭照,給我一條上傳網址 Note over S: 2. 用自己的憑證產一條
presigned PUT URL
(純本機運算,不連 S3) S-->>B: 3. 回傳這條 PUT URL B->>O: 4. 直接 PUT 檔案上 S3(帶著這條網址) O-->>B: 5. 上傳成功
拆開來講四步:
PUT 上 S3。整個過程最關鍵的一句話:你的 AWS 憑證從頭到尾只待在後端,瀏覽器只拿到一條「已經簽好名的網址」,從沒碰過任何憑證。 檔案本體也從沒流經你的後端——它從瀏覽器直達 S3。用 AWS 官方部落格的話說,到了第 4 步:
At this point, the caller application is interacting directly with the S3 service and not with your API endpoint.
下載(presigned GET)的資料流是同一個形狀的鏡像:前端(或任何人)跟後端要一條下載連結 → 後端產一條 presigned GET URL 回傳 → 對方拿這條直接跟 S3 要檔案。差別只在 method,以及「檔案是流出來(GET)還是流進去(PUT)」。
這是最多人搞錯的一點,所以獨立講。很多人以為「pre-signed URL 用一次就作廢了」——不是。 S3 官方文件白紙黑字:
You can use the presigned URL multiple times, up to the expiration date and time.
也就是在到期前,同一條 URL 想用幾次就用幾次。它的「失效條件」是時間到期(以及 Level 1 提過的「簽它的憑證被撤銷/過期」),而不是「被用過一次」。
實務上這代表什麼?
想要「真正只能用一次」的效果,得靠別的手段(例如把期限設得極短、或用一次性的後端流程),純靠 pre-signed URL 本身做不到。安全期限怎麼拿捏是 Level 5 的題目,這裡先建立「它預設可重複使用」這個正確認知。
把這一站的能力用兩個真實需求驗收一下:
需求 A:「使用者要上傳大頭照」
avatars/user-123.jpg)回傳 → 瀏覽器直接把照片 PUT 上 S3。需求 B:「產一條 24 小時有效的下載連結」
能把這兩題答成上面這樣,這一站就過關了。
為了讓這站聚焦,這些黑箱先點名、defer 到後面:
X-Amz-Signature、X-Amz-Credential… 到底怎麼算出來的(SigV4 演算法)→ Level 3。GetPreSignedUrlRequest / MinIO SDK)→ Level 4。