PostObject使用HTML表單上傳檔案到指定bucket。
Post作為Put的替代品,使得基於瀏覽器上傳檔案到bucket成為可能。Post Object的消息實體通過多重表單格式(multipart/form-data)編碼,在Put Object操作中參數通過HTTP要求標頭傳遞,在Post操作中參數則作為消息實體中的表單域傳遞。
Post object
請求文法
POST / HTTP/1.1
Host: BucketName.oss-cn-hangzhou.aliyuncs.com
User-Agent: browser_data
Content-Length:ContentLength
Content-Type: multipart/form-data; boundary=9431149156168
--9431149156168
Content-Disposition: form-data; name="key"
key
--9431149156168
Content-Disposition: form-data; name="success_action_redirect"
success_redirect
--9431149156168
Content-Disposition: form-data; name="Content-Disposition"
attachment;filename=oss_download.jpg
--9431149156168
Content-Disposition: form-data; name="x-oss-meta-uuid"
myuuid
--9431149156168
Content-Disposition: form-data; name="x-oss-meta-tag"
mytag
--9431149156168
Content-Disposition: form-data; name="OSSAccessKeyId"
access-key-id
--9431149156168
Content-Disposition: form-data; name="policy"
encoded_policy
--9431149156168
Content-Disposition: form-data; name="Signature"
signature
--9431149156168
Content-Disposition: form-data; name="file"; filename="MyFilename.jpg"
Content-Type: image/jpeg
file_content
--9431149156168
Content-Disposition: form-data; name="submit"
Upload to OSS
--9431149156168--
表單域
名稱 | 類型 | 描述 | 必須 |
---|---|---|---|
OSSAccessKeyId | 字元串 | Bucket 擁有者的Access Key Id。 預設值:無 限制:當bucket非public-read-write或者提供了policy(或Signature)表單域時,必須提供該表單域。 |
有條件的 |
policy | 字元串 | policy規定了請求的表單域的合法性。不包含policy表單域的請求被認為是匿名請求,並且只能訪問public-read-write的bucket。更詳細描述請參考下文 Post Policy。 預設值:無 限制:當bucket非public-read-write或者提供了OSSAccessKeyId(或Signature)表單域時,必須提供該表單域。 |
有條件的 |
Signature | 字元串 | 根據Access Key Secret和policy計算的簽名資訊,OSS驗證該簽名資訊從而驗證該Post請求的合法性。更詳細描述請參考下文 Post Signature。 預設值:無 限制:當bucket非public-read-write或者提供了OSSAccessKeyId(或policy)表單域時,必須提供該表單域。 |
有條件的 |
Cache-Control, Content-Type, Content-Disposition, Content-Encoding, Expires | 字元串 | REST要求標頭,更多的資訊見Put Object。 預設值:無 |
可選 |
file | 字元串 | 檔案或常值內容,必須是表單中的最後一個域。瀏覽器會自動根據檔案類型來設定Content-Type,會覆蓋用戶的設定。 OSS一次只能上傳一個檔案。 預設值:無 |
必須 |
key | 字元串 | 上傳檔案的object名稱。 如果需要使用用戶上傳的檔案名稱作為object名,使用${filename}變數。例如:如果用戶上傳了檔案b.jpg,而key域的值設定為/user/a/${filename},最終的object名為/user/a/b.jpg。 如果檔案名包含路徑,則去除檔案名中的路徑,例如用戶上傳了檔案a/b/c/b.jpg,則取檔案名為b.jpg,若key域的值設定為/user/a/${filename},最終的object名為/user/a/b.jpg 預設值:無 |
必須 |
success_action_redirect | 字元串 | 上傳成功後客戶端跳轉到的URL,如果未指定該表單域,返回結果由success_action_status表單域指定。如果上傳失敗,OSS返回錯誤碼,並不進行跳轉。 預設值:無 |
可選 |
success_action_status | 字元串 | 未指定success_action_redirect表單域時,該表單域指定了上傳成功後返回給客戶端的狀態碼。 接受值為200, 201, 204(預設)。 如果該域的值為200或者204,OSS返回一個空文檔和相應的狀態碼。 如果該域的值設定為201,OSS返回一個XML檔案和201狀態碼。 如果其值未設定或者設定成一個非法值,OSS返回一個空文檔和204狀態碼。 預設值:無 |
|
x-oss-meta-* | 字元串 | 用戶指定的user meta值。 OSS不會檢查或者使用該值。 預設值:無 |
可選 |
x-oss-server-side-encryption | 字元串 | 指定OSS建立object時的伺服器端加密編碼演算法。 合法值:AES256 |
可選 |
x-oss-object-acl | 字元串 | 指定oss建立object時的存取權限。 合法值:public-read,private,public-read-write |
可選 |
x-oss-security-token | 字元串 | 若本次訪問是使用STS臨時授權方式,則需要指定該項為SecurityToken的值,同時OSSAccessKeyId需要使用與之配對的臨時AccessKeyId,計算簽名時,與使用普通AccessKeyId簽名方式一致。 預設值:無 |
可選 |
響應Header
名稱 | 類型 | 描述 |
---|---|---|
x-oss-server-side-encryption | 字元串 | 如果請求指定了x-oss-server-side-encryption熵編碼,則響應Header中包含了該頭部,指明了所使用的密碼編譯演算法。 |
響應元素(Response Elements)
名稱 | 類型 | 描述 |
---|---|---|
PostResponse | 容器 | 保持Post請求結果的容器。 子節點:Bucket, ETag, Key, Location |
Bucket | 字元串 | Bucket名稱。 父節點:PostResponse |
ETag | 字元串 | ETag (entity tag) 在每個Object生成的時候被建立,Post請求建立的Object,ETag值是該Object內容的uuid,可以用於檢查該Object內容是否發生變化。 父節點:PostResponse |
Location | 字元串 | 新建立Object的URL。 父節點:PostResponse |
細節分析
- 進行Post操作要求對bucket有寫入權限,如果bucket為public-read-write,可以不上傳簽名資訊,否則要求對該操作進行簽名驗證。與Put操作不同,Post操作使用AccessKeySecret對policy進行簽名計算出簽名字元串作為Signature表單域的值,OSS會驗證該值從而判斷簽名的合法性。
- 無論bucket是否為public-read-write,一旦上傳OSSAccessKeyId, policy, Signature表單域中的任意一個,則另兩個表單域為必選項,缺失時OSS會返回錯誤碼:InvalidArgument。
- post操作提交表單編碼必須為“multipart/form-data”,即header中Content-Type為
multipart/form-data
;boundary=xxxxxx
這樣的形式,boundary為邊界字元串。 - 提交表單的URL為bucket網域名稱即可,不需要在URL中指定object。即請求行是
POST / HTTP/1.1
,不能寫成POST /ObjectName HTTP/1.1
。 - policy規定了該次Post請求中表單域的合法值,OSS會根據policy判斷請求的合法性,如果不合法會返回錯誤碼:AccessDenied。在檢查policy合法性時,policy中不涉及的表單域不進行檢查。
- 表單和policy必須使用UTF-8編碼,policy為經過UTF-8編碼和base64編碼的JSON。
- Post請求中可以包含額外的表單域,OSS會根據policy對這些表單域檢查合法性。
- 如果用戶上傳了Content-MD5要求標頭,OSS會計算body的Content-MD5並檢查一致性,如果不一致,將返回InvalidDigest錯誤碼。
- 如果POST請求中包含Header簽名資訊或URL簽名資訊,OSS不會對它們做檢查。
- 如果請求中攜帶以x-oss-meta-為首碼的表單域,則視為user meta,比如x-oss-meta-location。一個Object可以有多個類似的參數,但所有的user meta總大小不能超過8k。
- Post請求的body總長度不允許超過5G。若檔案長度過大,會返回錯誤碼:EntityTooLarge。
- 如果上傳指定了x-oss-server-side-encryption Header請求域,則必須設定其值為AES256,否則會返回400和錯誤碼:InvalidEncryptionAlgorithmError。指定該Header後,在回應標頭中也會返回該Header,OSS會對上傳的Object進行加密編碼儲存,當這個Object被下載時,回應標頭中會包含x-oss-server-side-encryption,值被設定成該Object的密碼編譯演算法。
- 表單域為大小寫不敏感的,但是表單域的值為大小寫敏感的。
樣本
- 請求樣本:
POST / HTTP/1.1 Host: oss-example.oss-cn-hangzhou.aliyuncs.com Content-Length: 344606 Content-Type: multipart/form-data; boundary=9431149156168 --9431149156168 Content-Disposition: form-data; name="key" /user/a/${filename} --9431149156168 Content-Disposition: form-data; name="success_action_status" 200 --9431149156168 Content-Disposition: form-data; name="Content-Disposition" content_disposition --9431149156168 Content-Disposition: form-data; name="x-oss-meta-uuid" uuid --9431149156168 Content-Disposition: form-data; name="x-oss-meta-tag" metadata --9431149156168 Content-Disposition: form-data; name="OSSAccessKeyId" 44CF9590006BF252F707 --9431149156168 Content-Disposition: form-data; name="policy" eyJleHBpcmF0aW9uIjoiMjAxMy0xMi0wMVQxMjowMDowMFoiLCJjb25kaXRpb25zIjpbWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsIDAsIDEwNDg1NzYwXSx7ImJ1Y2tldCI6ImFoYWhhIn0sIHsiQSI6ICJhIn0seyJrZXkiOiAiQUJDIn1dfQ== --9431149156168 Content-Disposition: form-data; name="Signature" kZoYNv66bsmc10+dcGKw5x2PRrk= --9431149156168 Content-Disposition: form-data; name="file"; filename="MyFilename.txt" Content-Type: text/plain abcdefg --9431149156168 Content-Disposition: form-data; name="submit" Upload to OSS --9431149156168--
- 返回樣本:
HTTP/1.1 200 OK x-oss-request-id: 61d2042d-1b68-6708-5906-33d81921362e Date: Fri, 24 Feb 2014 06:03:28 GMT ETag: 5B3C1A2E053D763E1B002CC607C5A0FE Connection: keep-alive Content-Length: 0 Server: AliyunOSS
Post Policy
Post請求的policy表單域用於驗證請求的合法性。 policy為一段經過UTF-8和base64編碼的JSON文本,聲明了Post請求必須滿足的條件。雖然對於public-read-write的bucket上傳時,post表單域為可選項,我們強烈建議使用該域來限制Post請求。
policy樣本
{ "expiration": "2014-12-01T12:00:00.000Z",
"conditions": [
{"bucket": "johnsmith" },
["starts-with", "$key", "user/eric/"]
]
}
Post policy中必須包含expiration和condtions。
Expiration
Expiration項指定了policy的過期時間,以ISO8601 GMT時間表示。例如”2014-12-01T12:00:00.000Z”指定了Post請求必鬚髮生在2014年12月1日12點之前。
Conditions
Conditions是一個列表,可以用於指定Post請求的表單域的合法值。注意:表單域對應的值在檢查policy之後進行擴充,因此,policy中設定的表單域的合法值應當對應於擴充之前的表單域的值。Policy中支援的conditions項見下表:
名稱 | 描述 |
---|---|
content-length-range | 上傳檔案的最小和最大允許大小。 該condition支援contion-length-range匹配方式。 |
Cache-Control, Content-Type, Content-Disposition, Content-Encoding, Expires | HTTP要求標頭。 該condition支援精確匹配和starts-with匹配方式。 |
key | 上傳檔案的object名稱。 該condition支援精確匹配和starts-with匹配方式。 |
success_action_redirect | 上傳成功後的跳轉URL地址。 該condition支援精確匹配和starts-with匹配方式。 |
success_action_status | 未指定success_action_redirect時,上傳成功後的返回狀態碼。 該condition支援精確匹配和starts-with匹配方式。 |
x-oss-meta-* | 用戶指定的user meta。 該condition支援精確匹配和starts-with匹配方式。 |
如果Post請求中包含其他的表單域,可以將這些額外的表單網域加入到policy的conditions中,conditions不涉及的表單域將不會進行合法性檢查。
Conditions匹配方式
Conditions匹配方式 | 描述 |
---|---|
精確匹配 | 表單域的值必須精確匹配conditions中聲明的值。如指定key表單域的值必須為a: {“key”: “a”} 同樣可以寫為: [“eq”, “$key”, “a”] |
Starts With | 表單域的值必須以指定值開始。例如指定key的值必須以/user/user1開始: [“starts-with”, “$key”, “/user/user1”] |
指定檔案大小 | 指定所允許上傳的檔案最大大小和最小大小,例如允許的檔案大小為1到10位元組: [“content-length-range”, 1, 10] |
逸出字元
於在 Post policy 中 $ 表示變數,所以如果要描述 $,需要使用逸出字元\$。除此之外,JSON 將對一些字元進行轉義。下圖描述了 Post policy 的 JSON 中需要進行轉義的字元。
逸出字元 | 描述 |
---|---|
\/ | 斜杠 |
\ | 反斜線 |
\” | 雙引號 |
\$ | 美元符 |
\b | 空格 |
\f | 換頁 |
\n | 換行 |
\r | 回車 |
\t | 水平定位字元 |
\uxxxx | Unicode 字元 |
Post Signature
對於驗證的Post請求,HTML表單中必須包含policy和Signature資訊。policy控制請求中那些值是允許的。計算Signature的具體流程為:
- 建立一個 UTF-8 編碼的 policy。
- 將 policy 進行 base64 編碼,其值即為 policy 表單域該填入的值,將該值作為將要簽名的字元串。
- 使用 AccessKeySecret 對要簽名的字元串進行簽名,簽名方法與Head中籤名的計算方法相同(將要簽名的字元串替換為 policy 即可),請參見在Header中包含簽名。
樣本 Demo
Web 端表單直傳 OSS 樣本 Demo,請參見JavaScript客戶端簽名直傳。