使用 Play 游戏服务发布 API 上传图片

通过 Play 游戏服务发布 API,您可以为游戏资源上传图片。

上传选项

通过 Play 游戏服务发布 API,您可以上传某些类型的二进制数据或媒体。您可上传数据的具体特性在支持媒体上传的任何方法的参考页面上都有详细说明

  • 最大上传文件大小:通过此方法可以存储的最大数据量。

  • 支持的媒体 MIME 类型:您可以使用此方法存储的二进制数据类型。

您可以通过以下任一方式发出上传请求。使用 `uploadType` 请求参数指定您使用的方法。

  • 简单上传uploadType=media。用于快速传输较小文件,例如 5 MB 或更小的文件。

  • 分段上传uploadType=multipart。用于快速传输较小文件和元数据;在单个请求中传输文件及其描述元数据。

  • 可续传上传uploadType=resumable。用于可靠传输,对于较大文件尤其重要。使用此方法时,您可以使用会话启动请求,其中可选择包含元数据。这对于大多数应用来说是一种很好的策略,因为它也适用于较小的文件,但每次上传时会多发出一个 HTTP 请求。

上传媒体时,您会使用一个特殊 URI。实际上,支持媒体上传的方法有两个 URI 端点

  • 用于媒体的 /upload URI。上传端点的格式是带有“/upload”前缀的标准资源 URI。在传输媒体数据本身时使用此 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。设置为方法支持的一种上传媒体数据类型,具体请参阅发布 API 参考文档

  • Content-Length。设置为您正在上传的字节数。如果您使用分块传输编码,则不需要。

示例:简单上传

以下示例展示了 Play 游戏服务发布 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。设置为请求正文中的总字节数。请求的媒体部分必须小于此方法指定的最大文件大小。

请求正文的格式为 multipart/related 内容类型 RFC2387,并包含恰好两部分。这些部分由边界字符串标识,最终边界字符串后跟两个连字符。

分段请求的每个部分都需要一个额外的 Content-Type 头

  • 元数据部分:必须排在第一位,且 Content-Type 必须与支持的元数据格式之一匹配。

  • 媒体部分:必须排在第二位,且 Content-Type 必须与方法支持的媒体 MIME 类型之一匹配。

有关每种方法支持的媒体 MIME 类型列表和上传文件大小限制,请参阅发布 API 参考文档

示例:分段上传

以下示例展示了 Play 游戏服务发布 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 类型列表和上传文件大小限制,请参阅发布 API 参考文档

示例:可续传会话启动请求

以下示例展示了如何为 Play 游戏服务发布 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 状态码。此外,它还提供一个 Location 头,其中指定了您的可续传会话 URI。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。

复制并保存会话 URI,以便在后续请求中使用。

上传文件

要上传文件,请向您在上一步中获得的上传 URI 发送 PUT 请求。上传请求的格式为

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-Length 头外,Content-Range 头也是必需的

  • Content-Length。设置为数据块大小,或者可能更小(如最后一个请求的情况)。

  • Content-Range。设置为显示您正在上传文件中哪些字节。例如,Content-Range: bytes 0-524287/2000000 表示您正在提供 2,000,000 字节文件中的前 524,288 字节 (256 x 1024 x 2)。

恢复中断的上传

如果上传请求在收到响应之前终止,或者您收到服务器返回的 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
    
  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 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. 停止。报告或记录错误。

在上述列表中,random_number_milliseconds 是一个小于或等于 1000 的随机毫秒数。这是必要的,因为引入少量随机延迟有助于更均匀地分配负载并避免服务器蜂拥而至的可能性。random_number_milliseconds 的值必须在每次等待后重新定义。

当 n 为 5 时,算法终止。此上限可防止客户端无限次重试,并在请求被视为“不可恢复的错误”之前导致总共约 32 秒的延迟。更大的最大重试次数是可以的,尤其是当正在进行长时间上传时;只需确保将重试延迟限制在合理范围内,例如小于一分钟。

API 客户端库指南