可续传上传

使用适用于 Google API 的可续传上传协议,可以更可靠地上传视频。借助此协议,您可以在网络中断或其他传输失败后恢复上传操作,从而在网络故障时节省时间和带宽。

在以下情况下,使用可续传上传尤其有用:

  • 您正在传输大型文件。
  • 网络中断的可能性较高。
  • 上传操作来自带宽较低或互联网连接不稳定的设备(例如移动设备)。

本指南介绍了应用使用可续传上传流程发出的 HTTP 请求的顺序。本指南主要面向无法使用 Google API 客户端库的开发者,其中的部分库为可续传上传提供原生支持。事实上,YouTube Data API - 上传视频指南介绍了如何使用 Python 版 Google API 客户端库通过可续传上传流程上传视频。

注意:您也可以使用启用了 HTTPS 日志记录的 Google API 客户端库,查看针对可续传上传或任何其他 API 操作发出的一系列请求。例如,如需启用 Python 的 HTTP 跟踪记录,请使用 httplib2 库:

httplib2.debuglevel = 4

第 1 步 - 启动可续传会话

如需启动可续传视频上传,请向以下网址发送 POST 请求。在该网址中,将 part 参数值设为请求的相应值。请注意,参数值用于标识您要设置的包含属性的各个部分,还用于标识您希望 API 响应包含的部分。请求网址中的参数值必须经过网址编码。

https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=PARTS

将请求的正文设置为 video 资源。此外,还要设置以下 HTTP 请求标头:

  • Authorization - 请求的授权令牌。
  • Content-Length - 请求正文中提供的字节数。请注意,如果您使用分块传输编码,则无需提供此标头。
  • Content-Type - 将值设置为 application/json; charset=UTF-8
  • X-Upload-Content-Length - 后续请求中将要上传的字节数。将该值设置为您要上传的文件的大小。
  • x-upload-content-type - 您要上传的文件的 MIME 类型。您可以上传任何视频 MIME 类型 (video/*) 或 MIME 类型 application/octet-stream 的文件。

以下示例展示了如何启动可续传会话来上传视频。该请求会在 video 资源的 snippetstatus 部分中设置(并将检索)属性,还会在资源的 contentdetails 部分中检索属性。

post /upload/youtube/v3/videos?uploadType=resumable&part=parts http/1.1
host: www.googleapis.com
authorization: bearer auth_token
content-length: content_length
content-type: application/json; charset=utf-8
x-upload-content-length: x_upload_content_length
X-Upload-Content-Type: X_UPLOAD_CONTENT_TYPE

video resource

以下示例展示了一个 POST 请求,其中除了身份验证令牌以外,填充了以上所有值。此示例中的 categoryId 值对应于视频类别。您可以使用 API 的 videoCategories.list 方法检索受支持的类别列表。

POST /upload/youtube/v3/videos?uploadType=resumable&part=snippet,status,contentDetails HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer AUTH_TOKEN
Content-Length: 278
Content-Type: application/json; charset=UTF-8
X-Upload-Content-Length: 3000000
X-Upload-Content-Type: video/*

{
  "snippet": {
    "title": "My video title",
    "description": "This is a description of my video",
    "tags": ["cool", "video", "more keywords"],
    "categoryId": 22
  },
  "status": {
    "privacyStatus": "public",
    "embeddable": True,
    "license": "youtube"
  }
}

第 2 步 - 保存可续传会话 URI

如果请求成功,该 API 服务器将返回 200 (OK) HTTP 状态代码,并且响应中将包含 Location HTTP 标头,该标头指定可续传会话的 URI。这是您将用来上传视频文件的 URI。

以下示例展示了对第 1 步中的请求做出的 API 响应示例:

HTTP/1.1 200 OK
Location: https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&upload_id=xa298sd_f&part=snippet,status,contentDetails
Content-Length: 0

第 3 步 - 上传视频文件

从 API 响应中提取会话 URI 后,您需要将实际视频文件内容上传到该位置。请求的正文是您所上传视频的二进制文件内容。以下示例展示了请求的格式。

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: CONTENT_LENGTH
Content-Type: CONTENT_TYPE

BINARY_FILE_DATA

该请求会设置以下 HTTP 请求标头:

  • Authorization - 请求的授权令牌。
  • Content-Length - 您要上传的文件的大小。此值应与第 1 步中 X-Upload-Content-Length HTTP 请求标头的值相同。
  • Content-Type - 您要上传的文件的 MIME 类型。此值应与第 1 步中 X-Upload-Content-Type HTTP 请求标头的值相同。

第 4 步 - 完成上传流程

您的请求会导致出现以下任一情况:

  • 上传成功。

    API 服务器以 HTTP 201 (Created) 响应代码作为响应。响应的正文是您创建的 video 资源。

  • 您的上传未成功,但可以恢复。

    出现以下任一情况时,您应该都能继续上传:

    • 由于您的应用与 API 服务器之间的连接中断,因此您的请求已中断。在这种情况下,您不会收到 API 响应。

    • API 响应会指定以下任意 5xx 响应代码。在接收这些响应代码后,您的代码应恢复使用指数退避算法策略。

      • 500 - Internal Server Error
      • 502 - Bad Gateway
      • 503 - Service Unavailable
      • 504 - Gateway Timeout

    如需恢复上传,请按照下文中的检查上传状态恢复上传中的说明操作。请记住,每个可续传会话 URI 的生命周期都是有限的,最终会过期。因此,我们建议您在获得会话 URI 后立即执行可续传上传操作,并在发生中断后立即恢复中断的上传。

  • 上传永久失败

    对于上传失败的内容,响应中会包含错误响应,该错误有助于说明失败的原因。对于永久失败的上传,API 响应将具有 4xx 响应代码或 5xx 响应代码,而不是上面列出的代码。

    如果您发送的请求包含过期的会话 URI,服务器会返回 404 HTTP 响应代码 (Not Found)。在这种情况下,您需要启动新的可续传上传操作,获取新的会话 URI,然后使用新的 URI 从头开始上传。

第 4.1 步:检查上传状态

如需查看可续传上传中断的状态,请向您在第 2 步中检索到且在第 3 步中检索到的上传网址发送空 PUT 请求。在您的请求中,将 Content-Range 标头值设置为 bytes */CONTENT_LENGTH,其中 CONTENT_LENGTH 是要上传的文件的大小。

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: 0
Content-Range: bytes */CONTENT_LENGTH

第 4.2 步:处理 API 响应

如果上传已完成,则不管上传是否成功,该 API 都将返回与上传开始时发送的相同响应。

但是,如果上传中断或仍在进行,则 API 响应将具有 HTTP 308 (Resume Incomplete) 响应代码。在响应中,Range 标头会指定文件已成功上传的字节数。

  • 标头值通过 0 编入索引。因此,标头值 0-999999 表示文件的前 1,000,000 个字节已上传。
  • 如果尚未上传任何内容,则 API 响应将不包含 Range 标头。

以下示例响应显示了适用于可续传上传的 API 响应的格式:

308 Resume Incomplete
Content-Length: 0
Range: bytes=0-999999

如果 API 响应还包含 Retry-After 标头,请使用该标头的值来确定何时尝试恢复上传。

第 4.3 步:恢复上传

要继续上传,请向在第 2 步中捕获的上传网址发送另一个 PUT 请求。将请求正文设为视频文件尚未上传的部分的二进制代码。

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: REMAINING_CONTENT_LENGTH
Content-Range: bytes FIRST_BYTE-LAST_BYTE/TOTAL_CONTENT_LENGTH

PARTIAL_BINARY_FILE_DATA

您需要设置以下 HTTP 请求标头:

  • Authorization - 请求的授权令牌。

  • Content-Length - 尚未上传的内容的大小(以字节为单位)。如果您要上传文件的其余部分,可以通过用 TOTAL_CONTENT_LENGTH 值减去 FIRST_BYTE 值来计算该值。这两个值都用于 Content-Range 标头。

  • Content-Range - 您要上传文件的部分。标头值由三个值组成:

    • FIRST_BYTE - 继续上传所用的字节的编号(从 0 开始)。此值比在上一步检索到的 Range 标头中的第二个数字高一个数字。在前面的示例中,Range 标头值为 0-999999,因此后续恢复上传的第一个字节将为 1000000

    • LAST_BYTE - 您要上传的二进制文件最后一个字节的从 0 开始的索引。通常,这是文件中的最后一个字节。例如,如果文件大小为 3000000 字节,则文件中的最后一个字节将为 2999999

    • TOTAL_CONTENT_LENGTH - 视频文件的总大小(以字节为单位)。此值与原始上传请求中指定的 Content-Length 标头相同。

    注意:您无法上传二进制文件的非连续块。如果您尝试上传非连续的屏蔽设置,系统将不会上传任何剩余的二进制内容。

    因此,在恢复上传时,上传的第一个字节必须是在已成功上传到 YouTube 的最后一个字节之后的下一个字节。(请参阅第 4.2 步中对 Range 标头的讨论。

    因此,如果 Range 标头中的最后一个字节是 999999,则请求恢复上传的第一个字节必须是字节 1000000。(这两个数字都使用从 0 开始的索引。)如果您尝试从字节 999999 或更低版本(重叠字节)或字节 1000001 或更高版本(跳过字节)恢复上传,则不会上传任何二进制内容。

分块上传文件

如果发生网络中断,您的应用可以尝试将整个文件分成几块,然后发送一系列请求,按顺序上传分块,而不是尝试上传整个文件并在网络中断时恢复上传。几乎没有必要使用此方法,并且实际上不建议采用此方法,因为它需要额外的请求,而这会对性能产生影响。不过,如果您尝试在非常不稳定的网络上显示进度指示器,可能会很有用。

分块上传文件的说明与本指南前面所述的四个步骤几乎完全相同。但是,开始上传文件(第 3 步)和恢复上传(第 4.3 步)的请求会使用分块上传文件时以不同的方式设置 Content-LengthContent-Range 标头值。

  • Content-Length 标头值指定请求发送的分块的大小。请注意以下数据块大小限制:

    • 数据块大小必须是 256 KB 的倍数。(此限制不适用于最后一个数据块,因为整个文件的大小可能不是 256 KB 的倍数。)请注意,数据块越大,效率越高。

    • 每个上传序列中要用到的数据块大小必须相同,最后一个请求除外,该数据会指定最终数据块的大小。

  • Content-Range 标头指定请求中正在上传的文件中的字节。设置此值时,第 4.3 节中设置 Content-Range 标头的相关说明适用。

    例如,值 bytes 0-524287/2000000 表示请求发送的是一个 200 万字节文件中的前 524288 个字节 (256 x 2048)。

以下示例说明的是一系列请求(其中将分块上传 2,000,000 字节文件)中的第一项请求的格式:

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: 524888
Content-Type: video/*
Content-Range: bytes 0-524287/2000000

{bytes 0-524287}

如果最终请求确认请求成功,API 服务器会返回 308 (Resume Incomplete) 响应。响应格式将与上文第 4.2 步:处理 API 响应中所述的格式相同。

使用 API 响应的 Range 标头中返回的上限值来确定从何处开始上传下一个分块。按照第 4.3 步:恢复上传中的说明继续发送 PUT 请求,以上传后续文件块,直到整个文件上传完毕。

整个文件上传完毕后,服务器会使用 201 HTTP 响应代码 (Created) 进行响应,并返回新创建的视频资源所请求的部分。

如果有任何请求中断,或者您的应用收到任何 5xx 响应代码,请按照第 4 步中所述的步骤完成上传。不过,请不要继续上传文件的其余部分,只需从您恢复上传的位置继续上传数据块即可。请务必使用检查上传状态来确定继续上传文件的位置。请勿假定服务器已收到(或未收到)上个请求中发送的字节。

注意:您还可以请求所上传分块之间的有效上传状态。(上传操作无需中断即可检索其状态)。