使用 Play Games Services Publishing API 上傳圖片

Play Games Services Publishing API 可讓您上傳一張遊戲資源的圖片。

上傳選項

Play Games Services Publishing API 可讓您上傳特定類型的二進位資料或媒體。任何支援媒體上傳的方法都附有參考頁面,您可以在頁面上指定可上傳資料的特性:

  • 「Maximum upload file size」(上傳檔案大小上限):用這個方法可以儲存的資料量上限。

  • 「Accepted media MIME types」(接受的媒體 MIME 類型):用這個方法可以儲存的二進位資料類型。

您可以透過下列任何一種方式提出上傳要求,請使用 uploadType 要求參數指定您要使用的方法。

  • 簡易上傳uploadType=media。可快速傳輸較小的檔案,例如 5 MB 以下的檔案。

  • 多部分上傳作業uploadType=multipart。適合為較小型檔案和中繼資料進行快速傳輸作業;您可將檔案與描述該檔案的中繼資料,放進同一筆傳輸要求。

  • 支援續傳的上傳作業uploadType=resumable。較大型的檔案特別重視傳輸可靠性,而這正是一種較為可靠的傳輸方式。您可以用這個方法以工作階段啟動要求,並選擇是否包含中繼資料。另外,使用者如果要傳輸較小型的檔案,只需要每次上傳時額外發出一次 HTTP 要求,便也能使用這種傳輸方式,所以這可以說是適用於大多數應用程式的方案。

上傳媒體時會使用特殊的 URI。事實上,支援媒體上傳作業的方法都有兩個 URI 端點:

  • /upload URI,適用於媒體。上傳端點的格式,就是標準資源 URI 加上「/upload」前置字串。傳輸媒體資料本身時,請使用這個 URI。

    範例:POST /upload/games/v1configuration/images/resourceId/imageType/imageType

  • 標準資源 URI,適用於中繼資料。如果資源包含任何資料欄位,這些欄位會用以儲存描述已上傳檔案的中繼資料。建立或更新中繼資料值時,可以使用這個 URI。

    範例:POST /games/v1configuration/images/resourceId/imageType/imageType

簡易上傳

上傳檔案最直接的方法,就是建立簡易的上傳要求。如果符合下列任一條件,就很適合使用這個選項:

  • 檔案夠小,如果連線失敗也可以重新完整上傳。

  • 沒有中繼資料要傳送。會造成這種情況可能是因為,您打算另以個別要求傳送資源的中繼資料;或者根本就沒有可支援或可用的中繼資料。如要使用簡易上傳功能,請對該方法的 /upload URI 發出 POST 或 PUT 要求,並加入查詢參數 uploadType=media。例如:

POST https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=media

提出簡易上傳要求時使用的 HTTP 標頭包括:

  • Content-Type。依據 Publishing API 參考資料,設為選定方法能接受的上傳媒體資料類型。

  • Content-Length。設為要上傳的位元組數,但若使用區塊轉移編碼即不需要。

範例:簡易上傳

以下範例說明運用 Play Games Services Publishing API 的簡易上傳要求狀況。

POST /upload/games/v1configuration/images/resourceId/imageType/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

{
  "kind": "gamesConfiguration#imageConfiguration",
  "url": string,
  "resourceId": string,
  "imageType": string
}

多部分上傳

如果有要隨資料一起上傳的中繼資料,可以放進同一筆 multipart/related 要求就好但如果要傳送的資料夠小,就算連線失敗也能完整重傳一次,倒是可以考慮這種傳輸方式。

如要使用多部分上傳,請向方法的 /upload URI 提出 POSTPUT要求,並加入查詢參數 uploadType=multipart。例如:

POST https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=multipart

提出多部分上傳要求時,要使用的頂層 HTTP 標頭包括:

Content-Type:請設定為 multipart/related,並加入辨識各個要求部分使用的邊界字串。

Content-Length:請設定為要求主體中的位元組總數。要求中的媒體部分,必須小於針對這個方法指定的檔案大小上限。

要求的主體格式設定為多部分/相關內容類型 RFC2387,且僅包含兩個部分。這些部分是靠邊界字串來辨識的,而緊接在最後一個邊界字串後面會有兩個連字號。

多部分要求的每個部分都需要一個額外的 Content-Type 標頭:

  • 中繼資料部分:您必須先撰寫這個部分,且 Content-Type 必須符合系統接受的其中一種中繼資料格式。

  • 媒體部分:撰寫優先順序僅次於「中繼資料部分」,且 Content-Type 必須符合該方法可接受的其中一種媒體 MIME 類型。

如要瞭解各個方法可接受的媒體 MIME 類型清單,以及上傳檔案的大小限制,請參閱 Publishing API 參考資料

範例:多部分上傳作業

以下範例說明 Play Games Services Publishing API 的多部分上傳要求。

POST /upload/games/v1configuration/images/resourceId/imageType/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

{
  "kind": "gamesConfiguration#imageConfiguration",
  "url": string,
  "resourceId": string,
  "imageType": string
}

--foo_bar_baz
Content-Type: image/png

PNG data
--foo_bar_baz--

如果要求成功,伺服器會傳回 HTTP 200 OK 狀態碼,以及所有中繼資料:

HTTP/1.1 200
Content-Type: application/json

{
  "kind": "gamesConfiguration#imageConfiguration",
  "url": string,
  "resourceId": string,
  "imageType": string
}

支援續傳的上傳作業

如要更可靠地上傳資料檔案,可以使用支援續傳的上傳通訊協定。此通訊協定可讓您在通訊問題導致上傳作業的資料傳輸過程中斷之後,能夠繼續執行上傳作業。如果您要傳輸大型檔案,而且發生網路中斷或其他傳輸問題的可能性很高 (例如從行動裝置用戶端應用程式上傳時),這種方法就特別有用。這方法也能在網路發生問題時降低頻寬用量,因為您不需要從頭開始上傳大型檔案。

使用支援續傳的上傳作業的步驟包括:

  1. 啟動續傳工作階段。對包含中繼資料 (如果有的話) 的上傳 URI 提出初始要求。

  2. 儲存續傳工作階段 URI。儲存初始要求回應中傳回的工作階段 URI,這將用於此工作階段的其餘要求 上傳檔案。

  3. 將媒體檔案傳送到可續傳的工作階段 URI。

此外,使用支援續傳的上傳作業的應用程式需要擁有續傳中斷上傳作業的代碼。如果上傳作業中斷,請找出已成功接收多少資料,然後從那一點開始續傳。

啟動續傳工作階段。

如要開始多部分上傳,請向方法的 /upload URI 提出 POSTPUT 要求,並加入查詢參數 uploadType=resumable。例如:

POST https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=resumable

這個初始要求的主體會是空白的,或是只包含中繼資料;您將在後續的要求中,傳輸您要上傳的檔案中的實際內容。

請搭配初始要求使用下列 HTTP 標頭:

  • X-Upload-Content-Type:請設定為要在後續要求中傳輸的上傳資料媒體 MIME 類型。

  • X-Upload-Content-Length:請設定為要在後續要求中傳輸的上傳資料位元組數。如果在提出要求時不知道此位元組數,則可以省略這個標頭。

  • 如果要提供中繼資料,請使用 Content-Type。請根據中繼資料的資料類型設定。

  • Content-Length:請設定為您在該初始要求主體中提供的位元組數。如果您要使用區塊傳輸編碼,就不需要這個標頭。

如要瞭解各個方法可接受的媒體 MIME 類型清單,以及上傳檔案的大小限制,請參閱 Publishing API 參考資料

範例:續傳工作階段啟動要求

以下範例說明如何為 Play Games Services Publishing API 啟動續傳工作階段。

POST /upload/games/v1configuration/images/resourceId/imageType/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

{
  "kind": "gamesConfiguration#imageConfiguration",
  "url": string,
  "resourceId": string,
  "imageType": string
}

下一節將說明如何處理回應。

儲存續傳工作階段 URI

如果工作階段啟動要求成功,API 伺服器就會傳回包含 200 OK HTTP 狀態碼的回應。此外,API 伺服器還提供會指定續傳工作階段 URI 的 Location 標頭。如以下範例所示,Location 標頭包含 upload_id 查詢參數,可提供這個工作階段所用的唯一上傳 ID。

範例:續傳工作階段啟動作業的回應

以下是步驟 1 中要求的回應:

HTTP/1.1 200 OK
Location: https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=resumable&upload_id=xa298sd_sdlkj2
Content-Length: 0

如以上回應範例所示,Location 標頭的值,就是您將做為 HTTP 端點的工作階段 URI,且這個 HTTP 端點將用於執行實際檔案上傳作業或查詢上傳狀態。

請複製並儲存工作階段 URI,好讓您能夠在後續的要求中使用。

上傳檔案

如要上傳檔案,請傳送 PUT 要求至上一個步驟中取得的上傳 URI。上傳要求的格式如下:

PUT session_uri

提出續傳檔案上傳要求時,要使用的 HTTP 標頭包含 Content-Length。將其設定為要在此要求中上傳的位元組數,這通常是上傳檔案大小。

範例:續傳檔案上傳要求

以下是目前範例的一個續傳要求,可上傳全部 2,000,000 個位元組的 PNG 文件。

PUT https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/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 要求的某些類別而言也是如此。這個方式也能讓您執行其他操作,例如:讓預設不支援顯示上傳進度的舊版瀏覽器顯示上傳進度。

如果要將資料切割為片段後上傳,也需要 Content-Range 標頭,以及完整檔案上傳所需要的 Content-Length 標頭:

  • Content-Length:請設定為區塊大小,或是更少的位元組,因為最後一個要求的資料傳輸量就可能會小於區塊大小。

  • Content-Range:請設定來顯示您要上傳檔案中的哪些位元組。舉例來說,Content-Range: bytes 0-524287/2000000 代表您要提供 2,000,000 位元組檔案中的前 524,288 個位元組 (256 x 1024 x 2)。

範例:可續傳區塊分割檔案上傳要求

傳送前 524,288 個位元組的要求可能會是這樣:

PUT {session_uri} HTTP/1.1
Host: www.googleapis.com
Content-Length: 524288
Content-Type: image/png
Content-Range: bytes 0-524287/2000000

bytes 0-524288

如果要求成功,伺服器會回應 308 Resume Incomplete,並附上「Range」(範圍) 標頭,指出目前已經儲存的位元組總數:

HTTP/1.1 308 Resume Incomplete
Content-Length: 0
Range: bytes=0-524287

請使用在 Range 標頭中傳回的上限值,決定下一個區塊的開始位置。請繼續對檔案的每個區塊執行 PUT,直到整個檔案上傳完畢為止。

如果有任何區塊的 PUT 要求中斷,或是您從伺服器收到 HTTP 503 Service Unavailable 或任何其他的 5xx 回應,請依照「繼續執行中斷的上傳作業」小節所述的程序進行,但請勿上傳檔案的剩餘部分,而是要直接從那一點繼續上傳區塊。

重要事項:

  • 請務必在回應中使用 Range 標頭,決定下一個區塊的起始位置;不要假設伺服器收到上一個要求中傳送的所有位元組。

  • 每個上傳 URI 的生命週期都是有限,而且最終都會過期 (如果沒有使用的話,大約會在一天內過期)。因此,我們強烈建議您在取得上傳 URI 之後,盡快開始續傳上傳作業,並且要在上傳作業中斷之後盡快續傳。

  • 如果傳送的要求包含過期的上傳工作階段 ID,伺服器會傳回 404 Not Found 狀態碼。如果上傳工作階段發生無法復原的錯誤,伺服器會傳回 410 Gone 狀態碼。在這種情況下,您必須開始新的續傳上傳作業、取得新的上傳 URI,然後使用新的端點從頭開始上傳。

完整檔案上傳完畢後,伺服器會回應 HTTP 201 Created,並附上與此資源相關聯的所有中繼資料。如果這個要求已更新現有的實體,而非建立新的實體,已完成上傳作業的 HTTP 回應碼就會是 200 OK


繼續執行中斷的上傳作業

如果上傳要求在收到回應前就終止,或者您收到伺服器傳回的 HTTP 503 Service Unavailable 回應,那麼就需要繼續處理中斷的上傳作業。如要恢復正常的上傳作業,請按照下列步驟操作:

  1. 要求狀態。請向上傳 URI 提出空白的 PUT 要求,以便查詢上傳作業的目前狀態。對於此要求,HTTP 標頭應包含會指出目前在檔案中位置不明的 Content-Range。舉例來說,如果檔案的總長度是 2,000,000,請將 Content-Range 設定為 */2000000。如果不知道檔案的完整大小,請將 Content-Range 設為 */*

  2. 取得已上傳的位元組數:請處理狀態查詢的回應。伺服器會在自己的回應中使用 Range 標頭,指出當下已接收到哪些位元組。舉例來說,如果 Range 標頭是 0-299999,代表伺服器已接收到檔案的前 300,000 個位元組。

  3. 上傳剩餘的資料:最後,既然您已經知道要從哪裡繼續提出要求,請傳送剩餘的資料或目前的區塊。請注意,無論如何,您都必須要把剩餘的資料當做單獨的區塊來處理,因此您必須在繼續執行上傳作業時傳送 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
  1. 從上次停止的地方繼續上傳。下列要求會傳送檔案的剩餘位元組 (從位元組 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 Found410 Gone 錯誤,請從頭開始執行整個上傳作業。

指數輪詢

指數輪詢是網路應用程式的標準錯誤處理策略,用戶端可透過這種策略,以逐漸增加的次數定期重試失敗的要求。如果大量要求或繁重的網路流量導致伺服器傳回錯誤,指數輪詢就是處理這類錯誤的一種不錯的策略。相反地,處理與網路流量或回應時間相關的錯誤 (例如授權憑證無效或找不到檔案的錯誤) 並不是很有意義的策略。

在正確的使用之下,指數輪詢可以提升頻寬使用的效率,減少取得成功回應所需的要求數,並最大化並行環境中的要求總處理量。

下列是簡單的指數輪詢實作流程:

  1. 對 API 提出要求。
  2. 收到指出您應該要重試要求的 HTTP 503 回應。
  3. 等待 1 秒鐘 + random_number_milliseconds 毫秒,然後重試要求。
  4. 收到指出您應該要重試要求的 HTTP 503 回應。
  5. 等待 2 秒鐘 + random_number_milliseconds 毫秒,然後重試要求。
  6. 收到指出您應該要重試要求的 HTTP 503 回應。
  7. 等待 4 秒鐘 + random_number_milliseconds 毫秒,然後重試要求。
  8. 收到 HTTP 503 response,表示您應該重試要求。
  9. 等待 8 秒鐘 + random_number_milliseconds 毫秒,然後重試要求。
  10. 收到 HTTP 503 response,表示您應該重試要求。
  11. 等待 16 秒鐘 + random_number_milliseconds 毫秒,然後重試要求。
  12. 停止。回報或記錄錯誤。

在上述清單中,隨機數字是小於或等於 1,000 的隨機毫秒數。這是必要的,因為使用較小的隨機延遲有助於更平均地分散負載,並避免對伺服器產生衝擊的可能性。必須在每次等待之後重新定義 random_number_milliseconds 的值。

演算法已設定為會在 n 等於 5 時終止。這個上限可以防止用戶端一直重試下去,導致要求在總延遲時間達到約 32 秒之後,才會被視為「無法復原的錯誤」。您可以把重試次數的上限設高一點,尤其是在大型上傳作業執行的過程中;但請確保要把重試延遲時間的上限設定在合理的地方,例如短於一分鐘。

API 用戶端程式庫指南