您可以透過 Google Play Developer API 上傳編輯的圖片、APK 或expansionfiles。下文將以圖片為例。
上傳選項
您可以透過 Google Play Developer API 上傳特定類型的二進位資料或媒體。您可以針對支援媒體上傳作業的任何方法,在相關參照頁面上指定可上傳資料的特性:
- 「Maximum upload file size」:您可以使用這個方法儲存的資料量上限。
- 「Accepted media MIME types」:您可以使用這個方法儲存的二進位資料類型。
您可以透過下列任何一種方式提出上傳要求,請利用 uploadType
要求參數,指定您要使用的方法。
- 簡易上傳:
uploadType=media
。用於快速傳輸較小的檔案,例如在 5 MB 以下。 - 多部分上傳作業:
uploadType=multipart
。適合為較小型的檔案和中繼資料進行快速的傳輸作業;可在單一要求中,將檔案與描述該檔案的中繼資料一起傳輸完畢。 - 支援續傳的上傳作業:
uploadType=resumable
。可靠的傳輸作業,對於較大型的檔案特別重要。透過這個方法,您可以使用工作階段啟動要求,其中可以選擇是否包含中繼資料。對於大多數的應用程式而言,這是不錯的策略,因為這也適用於較小型的檔案,您只需要為每次上傳作業額外支付一次 HTTP 要求的費用即可。
當您上傳媒體時,會使用特殊的 URI。事實上,支援媒體上傳作業的方法都有兩個 URI 端點:
/upload URI,適用於媒體。上傳端點的格式,就是標準資源 URI 加上「/upload」前置字串。使用這個 URI 的時機 轉移媒體資料本身
範例:
POST /upload/androidpublisher/v3/applications/packageName/edits/editId/listings/language/imageType
標準資源 URI,適用於中繼資料。如果資源包含任何資料欄位,這些欄位會用來儲存描述已上傳檔案的中繼資料。建立或更新中繼資料值時,可以使用這個 URI。
範例:
POST /androidpublisher/v3/applications/packageName/edits/editId/listings/language/imageType
簡易上傳
上傳檔案最直接的方法,就是建立簡單的上傳要求。這個選項適合在下列情況下使用:
- 檔案夠小,如果連線失敗也可以重新完整上傳。
- 沒有中繼資料要傳送。如果您打算另以個別要求傳送資源的中繼資料,或者沒有支援或可用的中繼資料,就可能發生這種情況。
如要使用簡易上傳功能,請發出 POST
或 PUT
要求,
方法的 /upload URI,並加入查詢參數
uploadType=media
。例如:
POST https://www.googleapis.com/upload/androidpublisher/v3/applications/packageName/edits/editId/listings/language/imageType?uploadType=media
提出簡易上傳要求時使用的 HTTP 標頭包括:
範例:簡易上傳
以下範例顯示如何使用簡易上傳要求, Google Play Developer API。
POST /upload/androidpublisher/v3/applications/packageName/edits/editId/listings/language/imageType?uploadType=media HTTP/1.1 Host: www.googleapis.com Content-Type: image/png Content-Length: number_of_bytes_in_file Authorization: Bearer your_auth_token PNG data
如果要求成功,伺服器會傳回 HTTP 200 OK
狀態碼,以及所有中繼資料:
HTTP/1.1 200 Content-Type: application/json {
"image": {
"id": string,
"url": string,
"sha1": string
}
}
多部分上傳
如果您有要隨資料一起上傳的中繼資料,可以提出單一 multipart/related
要求。如果您要傳送的資料小到足以在連線失敗時再完整上傳一次,這就是個不錯的選擇。
如要使用多部分上傳作業,請向方法的 /upload URI 發出 POST
或 PUT
要求,並加入查詢參數
uploadType=multipart
,例如:
POST https://www.googleapis.com/upload/androidpublisher/v3/applications/packageName/edits/editId/listings/language/imageType?uploadType=multipart
提出多部分上傳要求時,要使用的頂層 HTTP 標頭包括:
Content-Type
:請設定成 multipart/related,並加入要用來辨識各個要求部分的邊界字串。Content-Length
:請設定成要求主體中的位元組總數。要求中的媒體部分,必須小於針對這個方法指定的檔案大小上限。
要求主體的格式為 multipart/related
內容類型 [RFC2387],其中包含兩個部分。這些部分是靠邊界字串來辨識的,而緊接在最後一個邊界字串後面會有兩個連字號。
多部分要求的每個部分都需要一個額外的 Content-Type
標頭:
- 中繼資料部分:必須是要求的第一個部分,且
Content-Type
必須符合系統接受的其中一種中繼資料格式。 - 媒體部分:必須是要求的第二個部分,且
Content-Type
必須符合該方法可接受的其中一種媒體 MIME 類型。
如要瞭解每個方法的可接受媒體 MIME 類型清單,以及上傳檔案的大小限制,請參閱 API 參考資料。
注意:如果您只需要建立或更新中繼資料部分,不會上傳相關聯的資料,您只要把 POST
或 PUT
要求傳送給標準資源端點即可:https://www.googleapis.com/androidpublisher/v3/applications/packageName/edits/editId/listings/language/imageType
範例:多部分上傳作業
以下範例顯示 Google Play Developer API 的多部分上傳要求。
POST /upload/androidpublisher/v3/applications/packageName/edits/editId/listings/language/imageType?uploadType=multipart HTTP/1.1 Host: www.googleapis.com Authorization: Bearer your_auth_token Content-Type: multipart/related; boundary=foo_bar_baz Content-Length: number_of_bytes_in_entire_request_body --foo_bar_baz Content-Type: application/json; charset=UTF-8 {
"image": {
"id": string,
"url": string,
"sha1": string
}
} --foo_bar_baz Content-Type: image/png PNG data --foo_bar_baz--
如果要求成功,伺服器會傳回 HTTP 200 OK
狀態碼,以及所有中繼資料:
HTTP/1.1 200 Content-Type: application/json {
"image": {
"id": string,
"url": string,
"sha1": string
}
}
支援續傳的上傳作業
如要更可靠地上傳資料檔案,可以使用支援續傳的上傳通訊協定。如因通訊問題導致資料傳輸過程遭到中斷,之後可透過此通訊協定繼續執行上傳作業。如要傳輸大型檔案,但很可能發生網路中斷或其他傳輸問題 (例如從行動裝置用戶端應用程式上傳時),這種方法就特別有用。此外,這種方法也能在發生網路問題時降低頻寬用量,因為不需要從頭開始上傳大型檔案。
使用支援續傳的上傳作業的步驟包括:
- 啟動可續傳工作階段。對包含中繼資料 (如果有的話) 的上傳 URI 提出初始要求。
- 儲存可續傳工作階段 URI。儲存在初始要求回應中傳回的工作階段 URI;您會在這個工作階段的剩餘要求中用到它。
- 上傳檔案。將媒體檔案傳送到可續傳工作階段 URI。
此外,使用可續傳上傳功能的應用程式,必須擁有繼續執行中斷的上傳作業小節中的程式碼。如果上傳作業中斷,請找出已成功接收多少資料,然後從那一點開始續傳。
注意:上傳 URI 會在一週後失效。
步驟 1:啟動可續傳的工作階段
如要啟動支援續傳的上傳作業,請向該方法的 /upload URI 發出 POST
或 PUT
要求,並加入查詢參數
uploadType=resumable
,例如:
POST https://www.googleapis.com/upload/androidpublisher/v3/applications/packageName/edits/editId/listings/language/imageType?uploadType=resumable
這個初始要求的主體會是空白的,或是只包含中繼資料。您將在後續要求中,傳輸要上傳的檔案中的實際內容。
請將下列 HTTP 標頭與初始要求搭配使用:X-Upload-Content-Type
:請設為要在後續要求中傳輸的上傳資料媒體 MIME 類型。X-Upload-Content-Length
:請設定為要在後續要求中傳輸的上傳資料位元組數。如果您在提出該要求時不知道這個位元組數,可以省略這個標頭。- 如果要提供中繼資料,請使用
Content-Type
。請根據中繼資料的資料類型來設定。 Content-Length
:請設定為您在該初始要求主體中提供的位元組數。如果您要使用區塊傳輸編碼,就不需要這個標頭。
如要瞭解每個方法的可接受媒體 MIME 類型清單,以及上傳檔案的大小限制,請參閱 API 參考資料。
範例:可續傳工作階段啟動要求
以下範例說明如何為 Google Play Developer API 啟動支援續傳的工作階段。
POST /upload/androidpublisher/v3/applications/packageName/edits/editId/listings/language/imageType?uploadType=resumable HTTP/1.1 Host: www.googleapis.com Authorization: Bearer your_auth_token Content-Length: 38 Content-Type: application/json; charset=UTF-8 X-Upload-Content-Type: image/png X-Upload-Content-Length: 2000000 {
"image": {
"id": string,
"url": string,
"sha1": string
}
}
注意:針對不含中繼資料的初始可續傳更新要求,請將要求主體留白,並將 Content-Length
標頭設定為 0
。
下一節將說明如何處理回應。
步驟 2:儲存可續傳的工作階段 URI
如果工作階段啟動要求成功,API 伺服器就會傳回包含 200 OK
HTTP 狀態碼的回應。此外,API 伺服器還提供會指定可續傳工作階段 URI 的 Location
標頭。如以下範例所示,Location
標頭包含 upload_id
查詢參數,可提供這個工作階段所用的唯一上傳 ID。
範例:可續傳工作階段啟動作業的回應
以下是步驟 1 中要求的回應:
HTTP/1.1 200 OK Location: https://www.googleapis.com/upload/androidpublisher/v3/applications/packageName/edits/editId/listings/language/imageType?uploadType=resumable&upload_id=xa298sd_sdlkj2 Content-Length: 0
如以上回應範例所示,Location
標頭的值,就是您將做為 HTTP 端點的工作階段 URI,且這個 HTTP 端點將用於執行實際檔案上傳作業或查詢上傳狀態。
請複製並儲存工作階段 URI,好讓您能夠在後續的要求中使用。
步驟 3:上傳檔案
如要上傳檔案,請傳送 PUT
要求給您在上一個步驟中取得的上傳 URI。上傳要求的格式如下:
PUT session_uri
當您在提出可續傳檔案上傳要求時,要使用的 HTTP 標頭包含 Content-Length
。請把它設定為您要在這個要求中上傳的位元組數,這通常就是上傳檔案的大小。
範例:可續傳檔案上傳要求
以下是目前範例的一個續傳要求,可上傳全部 2,000,000 個位元組的 PNG 文件。
PUT https://www.googleapis.com/upload/androidpublisher/v3/applications/packageName/edits/editId/listings/language/imageType?uploadType=resumable&upload_id=xa298sd_sdlkj2 HTTP/1.1 Content-Length: 2000000 Content-Type: image/png bytes 0-1999999
如果要求成功,伺服器會傳回包含 HTTP 201 Created
的回應,加上與這個資源相關聯的所有中繼資料。如果可續傳工作階段的初始要求曾經是 PUT
,如要更新現有資源,成功的回應就會是 200 OK
,加上與這個資源相關聯的所有中繼資料。
如果上傳要求中斷,或是您從伺服器收到 HTTP 503 Service Unavailable
或任何其他的 5xx
回應,請依照繼續執行中斷的上傳作業小節所述的程序進行。
將檔案以區塊的形式上傳
透過可續傳的上傳作業,您可將檔案切割為片段,然後傳送一系列要求來依序上傳每個片段。這不是大家偏好的方式,因為您必須承擔與額外的要求相關聯的效能成本,而這通常是沒有必要的。然而,您可能需要使用切割成區塊的方式,減少要在任何單一要求中傳輸的資料量。當個別的要求有固定的時間限制時,這方式就很有用,對於 Google App Engine 要求的某些類別而言也是如此。這方式也能讓您做些其他的事,例如讓預設不支援顯示上傳進度的舊版瀏覽器顯示上傳進度。
繼續執行中斷的上傳作業
如果上傳要求在您收到回應之前就終止了,或是您收到伺服器傳回的 HTTP 503 Service Unavailable
回應,您就必須繼續執行中斷的上傳作業。步驟如下:
- 要求狀態:請向上傳 URI 提出空白的
PUT
要求,以便查詢上傳作業目前的狀態。針對這個要求,HTTP 標頭應該包含會指出目前在檔案中位置不明的Content-Range
。舉例來說,如果檔案的總長度是 2,000,000,請將Content-Range
設定為*/2000000
。如果您不知道檔案的完整大小,請將Content-Range
設定為*/*
。附註:您可以在不同區塊的上傳作業之間提出狀態要求,而不是只能在上傳中斷時提出要求。舉例來說,當您要讓舊版瀏覽器顯示上傳進度時,這功能就很有用。
- 取得已上傳的位元組數:請處理狀態查詢的回應。伺服器會在自己的回應中使用
Range
標頭,指出當下已接收到哪些位元組。舉例來說,如果Range
標頭是0-299999
,代表伺服器已接收到檔案的前 300,000 個位元組。 - 上傳剩餘的資料:最後,既然您已經知道要從哪裡繼續提出要求,請傳送剩餘的資料或目前的區塊。請注意,無論如何,您都必須要把剩餘的資料當做單獨的區塊來處理,因此您必須在繼續執行上傳作業時傳送
Content-Range
標頭。
範例:繼續執行中斷的上傳作業
1) 要求上傳狀態。
以下要求使用 Content-Range
標頭,指出目前在 2,000,000 位元組檔案中的位置不明。
PUT {session_uri} HTTP/1.1 Content-Length: 0 Content-Range: bytes */2000000
2) 從回應擷取當下已經上傳的位元組數。
伺服器的回應會使用 Range
標頭,指出伺服器當下已經收到檔案的前 43 個位元組。請使用在 Range
標頭中的上限值,決定要從哪裡繼續上傳。
HTTP/1.1 308 Resume Incomplete Content-Length: 0 Range: 0-42
注意:如果上傳作業已經完成,狀態回應可能會是 201 Created
或 200 OK
。如果連線在所有位元組都已上傳之後,但在用戶端收到伺服器的回應之前中斷,就可能發生這種情況。
3) 從上次離開的位置續傳上傳作業。
以下要求透過傳送檔案的剩餘位元組 (從位元組 43 開始) 續傳上傳作業。
PUT {session_uri} HTTP/1.1 Content-Length: 1999957 Content-Range: bytes 43-1999999/2000000 bytes 43-1999999
最佳做法
當您要上傳媒體時,瞭解幾個與錯誤處理相關的最佳做法是很有用的。
- 請繼續或重新執行因連線中斷或因任何
5xx
錯誤導致失敗的上傳作業,這些錯誤包括:500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
- 如果您在繼續或重試上傳要求時,收到任何
5xx
伺服器錯誤,請使用指數輪詢策略。如果伺服器超載,就可能發生這些錯誤。在發生大量要求或存在繁重網路流量期間,指數輪詢可協助減輕這一類問題。 - 其他類型的要求不應透過指數輪詢處理,但您仍可重試其中一些要求。重試這些要求時,請限制重試的次數。舉例來說,您的程式碼可能會限制為在最多重試十次之後,才會回報錯誤。
- 如要處理在執行可續傳上傳作業時收到的
404 Not Found
和410 Gone
錯誤,請從頭開始執行整個上傳作業。
指數輪詢
指數輪詢是網路應用程式的標準錯誤處理策略,用戶端可透過這種策略,以逐漸增加的次數定期重試失敗的要求。如果大量要求或繁重的網路流量導致伺服器傳回錯誤,指數輪詢就是處理這類錯誤的一種不錯的策略。相反地,處理與網路流量或回應時間相關的錯誤 (例如授權憑證無效或找不到檔案的錯誤) 並不是很有意義的策略。
在正確的使用之下,指數輪詢可以提升頻寬使用的效率,減少取得成功回應所需的要求數,並最大化並行環境中的要求總處理量。
實作簡單指數輪詢的流程如下:
- 對 API 提出要求。
- 收到指出您應該要重試要求的
HTTP 503
回應。 - 等待 1 秒又 random_number_milliseconds 毫秒,然後重試要求。
- 收到指出您應該要重試要求的
HTTP 503
回應。 - 等待 2 秒又 random_number_milliseconds 毫秒,然後重試要求。
- 收到指出您應該要重試要求的
HTTP 503
回應。 - 等待 4 秒鐘 + random_number_milliseconds 毫秒,然後重試要求。
- 收到指出您應該要重試要求的
HTTP 503
回應。 - 等待 8 秒鐘 + random_number_milliseconds 毫秒,然後重試要求。
- 收到指出您應該要重試要求的
HTTP 503
回應。 - 等待 16 秒鐘 + random_number_milliseconds 毫秒,然後重試要求。
- 停止。報告或記錄錯誤。
在以上流程中,random_number_milliseconds 是小於或等於 1000 的隨機毫秒數。這是必要的,因為使用較小的隨機延遲有助於更平均地分散負載,並避免對伺服器產生衝擊的可能性。必須在每次等待之後重新定義 random_number_milliseconds 的值。
注意:等待時間一律是 (2 ^ n) + random_number_milliseconds,其中 n 是一開始定義為 0 的單調遞增整數。對於每個疊代 (每次要求),整數 n 會遞增 1。
演算法已設定為會在 n 等於 5 時終止。這個上限可以防止用戶端一直重試下去,導致要求在總延遲時間達到約 32 秒之後,才會被視為「無法復原的錯誤」。您可以把重試次數的上限設高一點,尤其是在大型上傳作業執行的過程中;但請確保要把重試延遲時間的上限設定在合理的地方,例如短於一分鐘。