使用适用于 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
- 尚未上传的内容的大小(以字节为单位)。如果您要上传文件的其余部分,可以通过用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-Length
和 Content-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 步中所述的步骤完成上传。不过,请不要继续上传文件的其余部分,只需从您恢复上传的位置继续上传数据块即可。请务必使用检查上传状态来确定继续上传文件的位置。请勿假定服务器已收到(或未收到)上个请求中发送的字节。
注意:您还可以请求所上传分块之间的有效上传状态。(上传操作无需中断即可检索其状态)。