通过使用适用于 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
资源的 snippet
和 status
部分中的属性,还会检索资源的 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-Length
和 Content-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 步中介绍的步骤完成上传。不过,您不必尝试上传文件的其余部分,只需从恢复上传的位置继续上传分块即可。请务必检查上传状态,以确定从何处继续上传文件。请勿假定服务器已收到上一请求中发送的所有(或任何)字节。
注意:您还可以请求了解已上传分块之间的有效上传的状态。(上传内容无需中断,您就可以检索其状态。)