上传选项
借助 Android Over The Air API,您可以上传软件包数据来创建新的软件包资源。这些是 可与一项或多项配置关联以便传送更新的 OTA 软件包 设备。
我们提供了适用于 Linux 和 Windows 的二进制文件,以便于上传 而无需实现下述协议。如果您想更深入地了解 请使用下述协议之一。
Linux
Windows
若要使用它,您首先需要创建一个服务账号并获取该账号的 JSON 密钥文件。
请点击此处参阅我们的账号创建指南。
获得二进制文件和密钥文件后,您可以使用命令行选项运行该文件,以指定
密钥文件、您的部署和您要上传的软件包。请使用 --help
查看所有选项
上传协议
您可以通过以下任一方式发出上传请求。
使用 X-Goog-Upload-Protocol
请求标头指定您要使用的方法。
- 多部分上传:
X-Goog-Upload-Protocol: multipart
。为了快速将 较小的文件和元数据;只需一个请求,即可传输文件以及对该文件进行说明的元数据。 - 可续传上传:
X-Goog-Upload-Protocol: resumable
。用于进行可靠的传输,这对于 文件。通过这种方法,您可以使用一个启动请求的会话,可以选择在其中包含元数据。对于大部分客户来说 因为它也适用于较小的文件,但每次上传时都要多发出一个 HTTP 请求。
多部分上传
如果您要发送的数据很小,那么这是一个不错的选择 以便在连接失败时再次完整上传。
要使用多部分上传,请向 /upload/package 发出 POST
请求
URI 并将 X-Goog-Upload-Protocol
设置为 multipart
。
发出分段上传请求时要使用的顶级 HTTP 标头包含:
Content-Type
。将此项设为 multipart/related,并在其中添加您要修改的定界字符串 来标识请求的各个部分Content-Length
。请将此项设为请求正文中的字节总数。
请求正文的格式为 multipart/related
内容
类型 [RFC2387],并且正好包含两个部分。
这两个部分由定界字符串标识,最后的定界字符串后跟两个连字符。
分段请求的每个部分都需要附加一个 Content-Type
标头:
- 元数据部分:必须位于第一部分,且
Content-Type
必须为application/json
。 - 媒体部分:必须位于第二部分,且
Content-Type
必须为application/zip
。
示例:分段上传
以下示例展示了针对 Android Over The Air API 的多部分上传请求。
POST /upload/package HTTP/1.1 Host: androidovertheair.googleapis.com Authorization: Bearer your_auth_token Content-Type: multipart/related; boundary=BOUNDARY Content-Length: number_of_bytes_in_entire_request_body --BOUNDARY Content-Type: application/json; charset=UTF-8 {"deployment": "id", "package_title": "title" } --BOUNDARY Content-Type: application/zip; charset=UTF-8 Package ZIP --BOUNDARY--
如果请求成功,服务器将返回 HTTP 200 OK
状态代码
HTTP/1.1 200
为方便起见,您可以使用 curl 和 oauth2l。以下是一个示例请求 假定您使用的是服务密钥(请参阅我们的 授权方法)。
示例 curl 请求
JSON={"deployment": "id", "package_title": "title" } SERVICE_KEY_FILE=path to your service key json file curl \ -H "$(./oauth2l header --json $SERVICE_KEY_FILE android_partner_over_the_air)" \ -H "Host: androidovertheair.googleapis.com" \ -H "X-Goog-Upload-Protocol: multipart" \ -H "Content-Type: multipart/form-data" \ -F "json=$JSON;type=application/json" \ -F "data=@update.zip;type=application/zip" \ androidovertheair.googleapis.com/upload/package
可续传上传
如需更可靠地上传数据文件,您可以使用“可续传上传”协议。此协议允许 可在因通信故障导致数据流中断后恢复上传操作。它 如果您要传输大型文件并且可能会发生网络中断 或某些其他传输故障很严重,例如从移动客户端应用上传时。它 也可以在出现网络故障时减少带宽使用量 从头开始上传大型文件。
可续传上传协议使用多个命令:
- 启动可续传会话。向包含 元数据,并建立唯一的可续传上传位置。
- 保存可续传会话 URI。保存 对初始请求的响应;您将用它来处理此会话的后续请求
- 上传文件。将整个或部分 ZIP 文件发送到可续传会话 URI。
此外,使用可续传上传的应用需要通过代码来恢复中断的上传。如果上传内容 了解已成功接收了多少数据,然后从该中断处恢复上传。
注意 :上传 URI 的有效期为 3 天。
第 1 步:启动可续传会话
如需启动可续传上传,请向 /upload/package 发出 POST
请求
URI 并将 X-Goog-Upload-Protocol
设置为 resumable
。
对于这个发起请求,正文必须只包含元数据;你会将实际的 您要在后续请求中上传的文件的内容。
请在初始请求中使用以下 HTTP 标头:X-Goog-Upload-Header-Content-Type
。这是要上传的文件的内容类型,必须设为application/zip
。X-Goog-Upload-Command
。设置为start
X-Goog-Upload-Header-Content-Length
。请将此项设为要在后续请求中传输的上传数据的字节数。 在发起此请求时,如果内容长度未知,那么您可以忽略此标头。Content-Type
。这是元数据的内容类型,必须设置为application/json
。Content-Length
。设置为此初始请求的正文中提供的字节数。
示例:可续传会话的启动请求
以下示例展示了如何为 Android Over The Air API 启动可续传会话。
POST /upload/package HTTP/1.1 Host: android/over-the-air.googleapis.com Authorization: Bearer your_auth_token Content-Length: 38 Content-Type: application/json; charset=UTF-8 X-Goog-Upload-Command: start X-Goog-Upload-Header-Content-Type: application/zip X-Goog-Upload-Header-Content-Length: 2000000 {"deployment": "id", "package_title": "title" }
下一部分将介绍如何处理响应。
第 2 步:保存可续传会话 URI
如果会话启动请求成功,API 服务器会返回 HTTP 200 OK
状态代码。
此外,它还会提供 X-Goog-Upload-URL
标头来指定您的可续传会话 URI。
以下示例中显示的 X-Goog-Upload-URL
标头包含一个 upload_id
查询参数
部分,其中提供了要用于此会话的唯一上传 ID。响应还包含 X-Goog-Upload-Status
标头,如果上传请求有效且被接受,该标头将为 active
。此状态可能是“final
”
如果上传被拒,则会发生此错误。
示例:可续传会话的启动响应
下面是对第 1 步中的请求的响应:
HTTP/1.1 200 OK X-Goog-Upload-Status: active X-Goog-Upload-URL: androidovertheair.googleapis.com/?upload_id=xa298sd_sdlkj2 Content-Length: 0
上面的响应示例中显示的 X-Goog-Upload-URL
标头的值是
您将用作 HTTP 端点的会话 URI,用于实际上传文件或查询上传状态。
请复制并保存该会话 URI,以便在后续请求中使用。
第 3 步:上传文件
要上传文件,请发送 POST
请求至您在
上一步。上传请求的格式如下所示:
POST session_uri
发出可续传文件上传请求时要使用的 HTTP 标头包括:
Content-Length
。请将此项设为您要在该请求中上传的字节数(通常为上传文件大小)。X-Goog-Upload-Command
。将此项设置为upload
和finalize
。X-Goog-Upload-Offset
。此字段指定应写入字节的偏移量。请注意,客户端 必须串行上传字节。
示例:可续传文件上传请求
下面是一个可续传请求,用于针对当前示例上传大小为 2000000 字节的整个 ZIP 文件。
POST /?upload_id=xa298sd_sdlkj2 HTTP/1.1 Host: androidovertheair.googleapis.com X-Goog-Upload-Protocol: resumable X-Goog-Upload-Command: upload, finalize X-Goog-Upload-Offset: 0 Content-Length: 2000000 Content-Type: application/zip bytes 0-1999999
如果请求成功,服务器会返回 HTTP 200 Ok
。
如果上传请求被中断,或者您收到 HTTP 503 Service Unavailable
或任何
其他 5xx
响应,请按照恢复中断的上传部分中列出的步骤进行操作。
分块上传文件
借助可续传上传,您可以将一个文件分成几块,然后发送一系列请求,按顺序上传每个分块。
这并不是首选方法,因为发送更多请求会降低性能,
通常不需要。建议客户端上传载荷的所有剩余字节
在每个 upload
命令中添加 finalize
命令。
不过,您可能需要使用分块来减少 单一请求。它还可以让您执行各种操作,例如为旧版浏览器提供上传进度指示 默认不支持上传进度的应用
恢复中断的上传
如果上传请求在收到响应之前被终止,或者您收到
HTTP 503 Service Unavailable
响应,则需要恢复中断的上传。具体操作步骤如下:
- 请求状态。通过向上传 URI 发出请求来查询上传的当前状态
并将
X-Goog-Upload-Command
设置为query
。注意:您不仅可以请求查询上传是否已被中断,还可以请求查询分块之间的状态。这是 (例如,您想在旧版浏览器上显示上传进度指示时)。
- 获取已上传的字节数。处理服务器针对状态查询返回的响应。服务器使用
X-Goog-Upload-Size-Received
标头来指明目前已收到多少个字节。 - 上传剩余的数据。最后,在知道从何处恢复请求后,请将
剩余数据或当前分块请注意,无论在何种情况下,您都需要将剩余数据视为单独的分块。
您需要在恢复上传时将
X-Goog-Upload-Offset
标头设置为适当的偏移量。
示例:恢复中断的上传
1) 请求了解上传状态。
POST /?upload_id=xa298sd_sdlkj2 HTTP/1.1 Host: androidovertheair.googleapis.com X-Goog-Upload-Command: query
与所有命令一样,客户端必须检查查询命令的 HTTP 响应中的 X-Goog-Upload-Status
标头。
如果存在此标头且值不是 active
,则表示上传已终止。
2) 从响应中提取目前已上传的字节数。
服务器的响应使用 X-Goog-Upload-Size-Received
标头来指明其已
目前已收到文件的前 43 个字节。
HTTP/1.1 200 OK X-Goog-Upload-Status: active X-Goog-Upload-Size-Received: 42
3) 从中断处恢复上传。
下面的请求通过发送文件中的剩余字节(从第 43 个字节开始)来恢复上传。
POST /?upload_id=xa298sd_sdlkj2 HTTP/1.1 Host: androidovertheair.googleapis.com X-Goog-Upload-Command: upload, finalize Content-Length: 1999957 X-Goog-Upload-Offset: 43 bytes 43-1999999
最佳做法
在上传媒体时,了解错误处理方面的一些最佳做法很有帮助。
- 恢复或重试由于连接中断或任何
5xx
错误而失败的上传,此类错误包括:500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
- 如果在恢复或重试上传请求时收到任何
5xx
服务器错误,请使用指数退避算法策略。如果服务器发生超载,则可能会出现此类错误。在出现大量请求或网络流量拥堵期间,指数退避有助于缓解这类问题。 - 不应通过指数退避算法来处理其他类型的请求,但仍然可以重试其中的许多请求。重试这些请求时,请限制重试的次数。例如,您的代码可以限制为重试 10 次或更少的次数就会报告错误。
- 执行可续传上传时,通过从头开始整个上传过程来处理
404 Not Found
错误。
指数退避算法
指数退避是网络应用的标准错误处理策略,在此过程中,客户端按照不断增加的时间间隔定期重试失败的请求。如果因大量的请求或网络流量拥堵而导致服务器返回错误,指数退避策略能够很好地处理此类错误。相反,此策略并不适合处理与网络流量或响应时间无关的错误,例如授权凭据无效或找不到文件这样的错误。
如果使用得当,指数退避还能提高带宽使用效率、减少获得成功响应所需的请求数,并最大程度地提高并发环境中的请求吞吐量。
实现简单指数退避的流程如下:
- 向 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 秒。重试更多次数是可以接受的,特别是在大数量上传正在进行的情况下;只需确保重试延迟时间的上限设置合理即可(比如说少于 1 分钟)。