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

Play 游戏服务发布 API 允许您为游戏资源上传图像。

上传选项

Play 游戏服务发布 API 允许您上传某些类型的二进制数据或媒体。您可上传数据的具体特征在任何支持媒体上传的方法的参考页面上指定

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

  • 接受的媒体 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。设置为方法接受的上传媒体数据类型之一,在发布 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 类型之一匹配。

请参阅发布 API 参考,了解每种方法的接受的媒体 MIME 类型列表以及上传文件的尺寸限制。

示例:分块上传

以下示例显示了 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-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 内部服务器错误
    • 502 错误网关
    • 503 服务不可用
    • 504 网关超时
  • 如果在恢复或重试上传请求时返回任何 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 响应,这表示您应该重试请求。
  9. 等待 8 秒 + random_number_milliseconds,并重试请求。
  10. 收到HTTP 503 响应,这表示您应该重试请求。
  11. 等待 16 秒 + random_number_milliseconds,并重试请求。
  12. 停止。报告或记录错误。

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

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

API 客户端库指南