關於上傳回調

OSS在檔案上傳完成時可以提供回調(Callback)給用戶的回調伺服器(Callback Server)。在上傳請求中攜帶相應的回調參數,即能實現上傳回調。支援上傳回調的 API 介面有:PutObjectPostObjectCompleteMultipartUpload。更詳細的介紹請參看開發人員指南API

说明
回調伺服器(Callback Server),有時也叫商務服務器。

應用場景

  • 通知。上傳回調的一種典型應用是授權的第三方上傳檔案時指定回調參數。上傳完成後OSS向回調伺服器發送回調請求。回調伺服器收到回調請後,記錄上傳資訊。

  • 處理、審查、統計等。回調伺服器收到回調請後,對上傳的檔案做處理、審查、統計等。

資料流

OSS上傳回調流程,如下圖:

上圖中的資料流含義如下表所示:

資料流 含義 說明
1 上傳檔案並攜帶回調參數[1] 通過SDK(PutObjectCompleteMultipartUploadPostObject完成。
2 OSS隱藏檔後發起回調 OSS向上傳請求中指定的CallbackUrl 發起POST[2] 請求,回調逾時時間是5秒[3]。
3 回調伺服器返回處理結果
  • 回調伺服器返回的消息體一定要是 Json 格式。
  • OSS認為非200請求為回調失敗[4]。
-
4 OSS返回上傳、回調結果 -
  • 上傳、回調都成功,返回200
  • 上傳成功、回調失敗返回203,ErrorCode為CallbackFailed,ErrorMessage描述錯誤原因。
说明
  • [1] 格式請參看SDK/PostObject
  • [2] 回調請求POST的格式請參見發起回調請求
  • [3] 逾時時間為固定值,不支援配置。
  • [4] 參數無效、回調失敗返回40x,逾時、無法串連返回50x

SDK/PostObject

上傳時可以通過設定回調參數,指定回調伺服器URL、發送給回調伺服器的數據、格式等。回調伺服器處理回調時,需要一些上下文資訊,如bucketobject等,通過系統變數指定;系統變數以外的上下文資訊,通過自訂變數指定。

上傳回調參數

上傳回調包括以下參數:

欄位 含義 說明
callbackUrl 回調伺服器位址 必選參數
callbackHost 回調請求消息頭中Host的值 選擇性參數,預設為callbackUrl
callbackBody 回調請求的消息體 必選參數,內容可以包括系統變數和自訂變數
callbackBodyType 回調請求消息頭中Content-Type的值,即callbackBody的資料格式 選擇性參數,支援application/x-www-form-urlencodedapplication/json,預設為前者

通過上傳請求攜帶上傳回調參數有兩種實現方式:

  • 通過消息頭中的x-oss-callback,攜帶回調參數。這種方式比較常用,推薦該方式。
  • 通過QueryString的callback,攜帶回調參數。

x-oss-callbackcallback的值建置規則如下:

Callback := Base64(CallbackJson)
CallbackJson := '{' CallbackUrlItem, CallbackBodyItem [, CallbackHostItem, CallbackBodyTypeItem] '}' 
CallbackUrlItem := '"'callbackUrl'"' ':' '"'CallbackUrlValue'"'
CallbackBodyItem := '"'callbackBody'"' ':' '"'CallbackBodyValue'"'
CallbackHostItem := '"'callbackHost'"' ':' '"'CallbackHostValue'"'
CallbackBodyTypeItem := '"'callbackBodyType'"' : '"'CallbackBodyType'"'
CallbackBodyType := application/x-www-form-urlencoded | application/json

CallbackJson的值,樣本如下:

{
    "callbackUrl" : "http://abc.com/test.php",
    "callbackHost" : "oss-cn-hangzhou.aliyuncs.com",
    "callbackBody" : "{\"bucket\":${mimeType}, \"object\":${object},\"size\":${size},\"mimeType\":${mimeType},\"my_var\":${x:my_var}}",
    "callbackBodyType" : "application/json"
}
{
    "callbackUrl" : "http://abc.com/test.php",
    "callbackBody" : "bucket=${bucket}&object=${object}&etag=${etag}&size=${size}&mimeType=${mimeType}&my_var=${x:my_var}"
}

系統變數及自訂變數

CallbackJson樣本中的 callbackBody 包括如${bucket}${object}${size} 的變數,即為OSS定義的系統變數,OSS回調時會用實際值替換掉系統變數。OSS定義的系統變數如下表:

變數 含義
${bucket} 儲存空間名稱
${object} 檔案名稱
${etag} 檔案的ETag
${size} 檔案大小
${mimeType} 檔案類型,如image/jpeg等
${imageInfo.height} 圖片高度
${imageInfo.width} 圖片寬度
${imageInfo.format} 圖片格式,如jpg、png等
说明
  • 系統變數大小寫敏感。
  • 系統的變數的格式一定是 ${bucket}
  • imageInfo針對於圖片格式,為非圖片格式值為空。

CallbackJson樣本中的callbackBody 包括如${x:my_var}的變數,即自訂變數,OSS回調時會用自訂的值替換掉自訂變數。自訂變數的值可以在上傳請求中定義並攜帶,有以下兩種方式:

  • 通過消息頭中的x-oss-callback-var,攜帶自訂變數。這種方式比較常用,也是推薦方式;
  • 通過QueryString的callback-var,攜帶自訂變數。

x-oss-callback-varcallback-var 的建置規則如下:

CallbackVar := Base64(CallbackVarJson)
CallbackVarJson := '{' CallbackVarItem [, CallbackVarItem]* '}'
CallbackVarItem := '"''x:'VarName'"' : '"'VarValue'"'

CallbackVarJson 的值,樣本如下:

{
    "x:my_var1" : "value1",
    "x:my_var2" : "value2"
}
说明
  • 自訂變數必須以x:開頭,大小寫敏感,格式是${x:my_var}
  • 自訂變數的長度受消息頭、URL的長度限制,建議自訂變數不超過10個,總長度不超過512Byte。

SDK使用樣本

部分SDK對上述步驟進行了封裝,如Java、JS,部分SDK需要使用上面的規則生成上傳回調參數和自訂變數,如Python、PHP、C。SDK的使用樣本如下:

SDK 上傳回調樣本 說明
Java CallbackSample.java 注意CallbackBody中的逸出字元。
Python object_callback.py -
PHP Callback.php 注意上傳的$options中OSS_CALLBACKOSS_CALLBACK_VAR不需要base64,SDK會做。
C# UploadCallbackSample.cs 注意使用 using 讀取 PutObjectResult.ResponseStream ,但要確保關閉PutObjectResult.ResponseStream
JS object.test.js -
C oss_callback_sample.c -
Ruby callback.rb -
iOS

上傳後回調通知

注意<var1> 的格式應該是x:var1
Andriod

上傳後回調通知

注意CallbackBody中的逸出字元。
说明
Go SDK尚不支援上傳回調。

PostObject使用樣本

PostObject支援上傳回調,回調參數通過表單域callback攜帶,自訂變數通過獨立的表單域攜帶,詳細請參看PostObjet

PostObject的使用樣本如下:

SDK 上傳回調樣本
Java PostObjectSample.java
Python object_post.py
JS JavaScript客戶端簽名直傳
C# PostPolicySample.cs

回調伺服器

回調伺服器(Callback Server),是一個HTTP伺服器,處理OSS發送的回調請求,POST消息。回調伺服器的URL即上傳回調參數中的callbackUrl。回調伺服器是用戶自己實現的處理邏輯,實現上傳數據的記錄、審查、處理、統計等。

回調簽名

回調伺服器為了確認收到的POST請求來自於OSS的上傳回調,需要驗證該POST消息的簽名。回調伺服器也可以不驗證簽名,直接處理該消息。為了提高回調伺服器的安全性,建議驗證消息簽名。回調簽名規則請參看回調簽名

说明
OSS的回調伺服器樣本中提供了簽名校驗的實現,推薦直接使用該部分代碼。
消息處理

回調伺服器的主要邏輯,對OSS的回調請求進行處理。以下幾點請注意:

  • 回調伺服器必須處理OSS的POST請求;
  • OSS回調的逾時時間是 5秒,回調伺服器必須在5秒內完成處理並返回;
  • 回調伺服器返回給OSS的消息體必須是JSON格式;
  • 回調伺服器是用戶自己的邏輯,OSS提供樣本而不提供具體商務邏輯實現。
實現樣本

回調伺服器的實現樣本如下:

語言 樣本 運行方法
Java AppCallbackServer.zip 解壓後執行java -jar oss-callback-server-demo.jar 9000
PHP callback-php-demo.zip Apache環境下部署運行。
Python callback_app_server.py.zip 解壓後執行python callback_app_server.py
Ruby oss-callback-server 執行ruby aliyun_oss_callback_server.rb

調試步驟

上傳回調的調試分為兩部分:上傳的客戶端、處理回調的回調伺服器。建議先調試客戶端上傳部分,再調試回調伺服器部分。兩部分單獨調試完成後,再運行完整的上傳回調。

調試客戶端

客戶端調試時,可使用OSS提供的回調伺服器http://callback.oss-demo.com:23450,即回調參數callbackUrl。該回調伺服器只驗證回調請求的簽名,對回調請求不做處理。對於簽名驗證成功的回調請求,返回{"Status":"OK"};簽名驗證失敗的回調請求,返回400 Bad Request;非POST請求返回501 Unsupported method。樣本回調伺服器的代碼請參看callback_app_server.py.zip

調試回調伺服器

回調伺服器是一個支援處理POST請求的HTTP伺服器,可以在OSS提供的樣本基礎上修改,也可以自己獨立實現。OSS提供的回調伺服器樣本:

語言 樣本 運行方法
Java AppCallbackServer.zip 解壓後執行java -jar oss-callback-server-demo.jar 9000
PHP callback-php-demo.zip Apache環境下部署運行。
Python callback_app_server.py.zip 解壓後執行python callback_app_server.py
C# callback-server-dotnet.zip 編譯後執行aliyun-oss-net-callback-server.exe 127.0.0.1 80
Go callback-server-go.zip 編譯後執行aliyun_oss_callback_server
Ruby oss-callback-server 執行ruby aliyun_oss_callback_server.rb

回調伺服器可以通過cURL命令調試,下面幾個命令可能會用到:

# 向回調伺服器發送消息體為 `object=test_obj` 的 `POST` 請求,可以使用如下命令 
curl -d "object=test_obj"  http://callback.oss-demo.com:23450 -v
# 向回調伺服器發送消息體為檔案 `post.txt` 內容 的 `POST` 請求,可以使用如下命令 
curl -d @post.txt  http://callback.oss-demo.com:23450 -v
#向回調伺服器發送消息體為檔案 `post.txt` 內容的 `POST` 請求,並攜帶指定的消息頭 `Content-Type`
curl -d @post.txt -H "Content-Type: application/json" http://callback.oss-demo.com:23450 -v
说明
  • 調試回調伺服器時,可以先忽略簽名驗證部分,因為cURL類比簽名功能比較困難。
  • 簽名驗證功能OSS樣本中已經提供,建議直接使用。
  • 回調伺服器建議有日誌功能,記錄收到的所有消息,方便調試、跟蹤。
  • 回調伺服器正確處理回調請求後,一定要返回200,而不是其它的20x
  • 回調伺服器返回給OSS的消息體,一定要是JSON格式,Content-Type設定為application/json

常見錯誤及原因

InvalidArgument
<Error>
  <Code>InvalidArgument</Code>
  <Message>The callback configuration is not json format.</Message>
  <RequestId>587C79A3DD373E2676F73ECE</RequestId>
  <HostId>bucket.oss-cn-hangzhou.aliyuncs.com</HostId>
  <ArgumentName>callback</ArgumentName>
  <ArgumentValue>{"callbackUrl":"8.8.8.8:9090","callbackBody":"{"bucket":${bucket},"object":${object}}","callbackBodyType":"application/json"}</ArgumentValue>
</Error>
原因:

回調參數設定錯誤,或參數格式錯誤。常見的錯誤是ArgumentValue之間的回調參數,不是有效JSON格式。在 JSON中\" 是逸出字元,如"callbackBody":"{"bucket":${bucket},"object":${object}}"應該為"callbackBody":"{\"bucket\":${bucket},\"object\":${object}}"。針對具體的SDK,請參看對應的上傳回調樣本,詳細請參考SDK使用樣本部分。

轉義後的字元 轉義前的字元
\\ \\\\
\\\”
\b \\b
\f \\f
\n \\n
\r \\r
\t \\t
CallbackFailed
<Error>
  <Code>CallbackFailed</Code>
  <Message>Response body is not valid json format.</Message>
  <RequestId>587C81A125F797621829923D</RequestId>
  <HostId>bucket.oss-cn-hangzhou.aliyuncs.com</HostId>
</Error>
原因:

回調伺服器返回給OSS的消息體非JSON格式。您可以通過curl -d "<Content>" <CallbackServerURL> -v或抓包確認內容。Windows下推薦使用工具Wireshark 抓包,Linux下使用命令tcpdump抓包。一些非法返回消息體如下:OK\357\273\277{"Status":"OK"}(即含有ef bb bf三個位元組的BOM頭)等。

<Error>
  <Code>CallbackFailed</Code>
  <Message>Error status : -1.OSS can not connect to your callbackUrl, please check it.</Message>
  <RequestId>587C8735355BE8694A8E9100</RequestId>
  <HostId>bucket.oss-cn-hangzhou.aliyuncs.com</HostId>
</Error>
原因:

回調伺服器處理時間超過5秒,OSS認為逾時。建議回調伺服器的處理邏輯修改為非同步,保證在5秒內處理完畢並返回結果OSS。

<Error>
  <Code>CallbackFailed</Code>
  <Message>Error status : -1 8.8.8.8:9090 reply timeout, cost:5000ms, timeout:5000ms (err -4, errno115)</Message>
  <RequestId>587C8D382AE0B92FA3EEF62C</RequestId>
  <HostId>bucket.oss-cn-hangzhou.aliyuncs.com</HostId>
</Error>
原因:

回調伺服器處理時間超過5秒,OSS認為逾時。

<Error>
  <Code>CallbackFailed</Code>
  <Message>Error status : 400.</Message>
  <RequestId>587C89A02AE0B92FA3C7981D</RequestId>
  <HostId>bucket.oss-cn-hangzhou.aliyuncs.com</HostId>
</Error>
原因:

回調伺服器返回給OSS的消息的狀態碼是400,請檢查回調伺服器的處理邏輯。

<Error>
  <Code>CallbackFailed</Code>
  <Message>Error status : 502.</Message>
  <RequestId>587C8D382AE0B92FA3EEF62C</RequestId>
  <HostId>bucket.oss-cn-hangzhou.aliyuncs.com</HostId>
</Error>
原因:

回調伺服器未啟動,或者缺少上傳回調參數中的CallbackUrl,或者OSS與回調伺服器的網路不通。推薦在ECS上部署回調伺服器,與OSS同屬內網可以節省流量費用,同時保證網路品質。

常用連結