可续传上传

通过使用适用于 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 - 尚未上传的内容的大小(以字节为单位)。如果您要上传文件的其余部分,则可以通过将 FIRST_BYTE 值从 TOTAL_CONTENT_LENGTH 值中减去来计算此值。这两个值都将在 Content-Range 标头中使用。

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

    • FIRST_BYTE - 从中恢复上传的字节数的数字索引(从 0 开始)。此值比上一步中检索到的 Range 标头中的第二个数字大 1。在前面的示例中,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 表示请求要发送某个 2,000,000 字节文件中的前 524,288 个字节 (256 x 2048)。

以下示例展示了将分块上传 200 万字节文件的一系列请求中第一个请求的格式:

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 标头中返回的上限值来确定从何处开始上传下一个分块。继续发送 PUT 请求(如第 4.3 步:恢复上传中所述),上传后续的文件分块,直到整个文件上传完毕。

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

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

注意:您还可以请求了解已上传分块之间的有效上传的状态。(上传内容无需中断,您就可以检索其状态。)