學習筆記:Pre-signed URL Level 2 — GET vs PUT(下載 / 上傳 / HEAD)

學習文章 · 2026-07-07 13:12

這是 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),就決定了拿到網址的人能做什麼。這一站就是在講這件事。

就愛考你

這幾題就是本文重點,也是讀完你該能用自己的話答出來的問題。先想想現在答不答得出來,帶著它們往下讀,讀完再回來對照。

  1. 同一條 pre-signed URL,簽的時候 method 是 GET 跟是 PUT,分別讓拿到網址的人能做什麼?看答案收合

    GET=讓對方下載這個物件;PUT=讓對方把一個檔案上傳到指定 key(key=檔案在 bucket 裡的路徑+檔名,如 avatars/user-123.jpg)。

    • 差別只在 method,底層簽章機制三種共用一套。
    • AWS 官方原文:GET for downloading,PUT for uploading,HEAD for reading object metadata。
  2. 用 presigned PUT 上傳時,如果那個 key 在 bucket 裡已經有檔案了,會發生什麼事?看答案收合

    (沒開版本控管時;版本控管=S3 幫你保留舊版本,這裡先當沒開)S3 直接用新檔覆蓋掉舊檔——不問你、不報錯、不另存。

    • 官方原話:if an object with the same key already exists…Amazon S3 replaces the existing object with the uploaded object。
    • 換大頭照場景這正合需求;不想被蓋就產 URL 時給不同 key(帶時間戳/亂數)。
  3. 除了下載和上傳,還有第三種常見操作也能 presign,它是拿來做什麼的?看答案收合

    presigned HEAD=只讀 metadata(檔案的描述資訊:多大、是圖片還是 PDF 之類),不回檔案內容

    • 因為 HTTP HEAD 的特性就是「只回 header(檔案的基本資訊欄位)、不回 body(檔案內容本身)」。
    • 用途:想先問「這檔多大、什麼類型」再決定要不要下載。
  4. 為什麼 AWS 建議「讓瀏覽器直接把檔案 PUT 上 S3」,而不是「先傳到你後端、再由後端存進 S3」?看答案收合

    別讓後端(=你自己的伺服器;前端=使用者的瀏覽器/網頁)當「二傳手」(=中轉/搬運工)去扛大檔的流量、CPU 和記憶體。

    • 直傳能別讓後端當「中轉站」替請求轉手,大幅減少網路流量與伺服器 CPU(AWS 原話:avoid proxying these requests…, significantly reduce network traffic and server CPU usage)。
    • 流量暴衝時,後端能專心處理別的請求,不必為了扛上傳而擴充。
    • 重活交給 S3(它本來就為海量物件而生),後端只發一張限時通行證。
  5. 畫出「瀏覽器直傳大頭照」的資料流:誰跟誰要什麼、誰產 URL、檔案往哪走?後端有碰到憑證嗎?看答案收合

    四步:① 前端跟後端一條上傳網址 → ② 後端用憑證產一條 presigned PUT URL(純本機、不連 S3)→ ③ 後端回傳這條 URL → ④ 瀏覽器拿它直接 PUT 檔案上 S3

    • 憑證只待在後端;瀏覽器只拿到一條簽好名的網址,從沒碰憑證。
    • 檔案本體從沒流經後端,從瀏覽器直達 S3。
  6. 一條 pre-signed URL 是「用一次就作廢」,還是「到期前可重複用很多次」?看答案收合

    到期前可重複使用很多次,不是一次性。

    • 官方原話:You can use the presigned URL multiple times, up to the expiration date and time。
    • 失效條件是時間到期(或簽它的憑證被撤銷/過期),不是「被用過一次」。
    • 所以一條下載連結貼群組,每個人點都能下載直到過期——這也是它是秘密的原因。
  7. 綜合題(過關):「上傳大頭照」和「產一條 24 小時下載連結」——各該用 PUT 還是 GET?資料流長怎樣?看答案收合

    上傳大頭照=PUT:前端要 URL → 後端產 presigned PUT URL(指定 key)回傳 → 瀏覽器直接 PUT 照片上 S3;撞名會覆蓋舊照(正合需求)。

    24 小時下載連結=GET:後端產一條有效期 24 小時的 presigned GET URL → 給對方 → 對方直接跟 S3 下載;期間可被重複點、多人用,故是秘密。

    能答成這樣,這一站就過關了。

一條網址三種身分:GET 下載、PUT 上傳、HEAD 看資訊

先給結論:你在簽 URL 的時候就決定了它是哪一種,靠的就是那個 HTTP method。AWS S3 官方文件把這件事講得很直白——建立 pre-signed URL 時,你要指定「一個 HTTP method」,並且列明:

GET for downloading objects, PUT for uploading, HEAD for reading object metadata

翻成白話,同樣一套「先簽好名的網址」機制,換個 method 就變成三種完全不同的用途:

小提醒:這三種的差別只在 method,簽章那套底層機制(把請求算成 X-Amz-Signature)三種是同一套。至於那段簽章到底怎麼算出來的、URL 裡那堆 X-Amz-* 各是什麼——那是 Level 3(SigV4) 的黑箱,這站先不拆,你只要記得「method 決定用途」。

PUT 的一個關鍵脾氣:key 撞名就直接蓋掉

這點很容易踩雷,特別記一下。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 卡不住大小」就好。

為什麼上傳要用 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. 上傳成功

拆開來講四步:

  1. 前端跟你後端「要」一條上傳網址(不是把檔案傳過去,只是要一張通行證)。
  2. 後端用自己的 AWS 憑證,產一條 presigned PUT URL——這步是純本機的數學運算,後端不會連到 S3(這點 Level 1 講過)。
  3. 後端把這條 URL 回傳給前端。
  4. 瀏覽器拿著這條 URL,直接把檔案 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)」。

一條 URL 不是一次性:到期前可以用很多次

這是最多人搞錯的一點,所以獨立講。很多人以為「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:「使用者要上傳大頭照」

需求 B:「產一條 24 小時有效的下載連結」

能把這兩題答成上面這樣,這一站就過關了。

這篇刻意沒碰的(後面站見)

為了讓這站聚焦,這些黑箱先點名、defer 到後面:

參考來源(實際爬過的權威連結)