执行可续传上传

概览

本页面介绍如何在 Cloud Storage JSON 和 XML API 中发出可续传上传请求。当数据流因通信故障而中断后,您可以利用此协议恢复上传操作。

如需了解如何在 Google Cloud CLI 和客户端库中使用可续传上传,请参阅工具和 API 如何使用可续传上传

所需的角色

如需获得执行可续传上传所需的权限,请让您的管理员为您授予以下角色之一:

  • 对于包含对象保留锁定的上传,请让您的管理员为您授予存储桶的 Storage Object Admin (roles/storage.objectAdmin) IAM 角色。

  • 对于其他所有情况,请让您的管理员为您授予存储桶的 Storage Object User (roles/storage.objectUser) IAM 角色。

这些预定义角色包含针对其各自的情况将对象上传到存储桶所需的权限。如需查看所需的确切权限,请展开所需权限部分:

  • storage.objects.create
  • storage.objects.delete
    • 只有覆盖现有对象的上传操作需要此权限。
  • storage.objects.setRetention
    • 只有包含对象保留锁定的上传操作才需要此权限。

您也可以使用其他预定义角色自定义角色来获得这些权限。

如需了解如何授予存储桶的角色,请参阅将 IAM 与存储桶搭配使用

启动可续传上传会话

如需启动可续传上传会话,请执行以下操作:

  1. 安装并初始化 gcloud CLI,以便为 Authorization 标头生成访问令牌。

  2. (可选)创建一个 JSON 文件,其中包含您要在上传的对象上设置的 metadata。例如,以下 JSON 文件将您要上传到的对象的 contentType 元数据设置为 image/png

    {
        "contentType": "image/png"
    }
  3. 使用 cURL,通过 POST Object 请求调用 JSON API

    curl -i -X POST --data-binary @METADATA_LOCATION \
        -H "Authorization: Bearer $(gcloud auth print-access-token)" \
        -H "Content-Type: application/json" \
        -H "Content-Length: INITIAL_REQUEST_LENGTH" \
        "https://storage.googleapis.com/upload/storage/v1/b/BUCKET_NAME/o?uploadType=resumable&name=OBJECT_NAME"

    其中:

    • METADATA_LOCATION 是 JSON 文件的本地路径,其中包含您在上一步中指定的可选元数据。如果您不添加元数据文件,请排除此文件以及 --data-binary @Content-Type 标头。
    • INITIAL_REQUEST_LENGTH 是此初始请求正文中的字节数,例如 79
    • BUCKET_NAME 是对象要上传到的存储桶的名称。例如 my-bucket
    • OBJECT_NAME 是您要为对象指定的网址编码名称。例如,pets/dog.png 的网址编码为 pets%2Fdog.png。如果您在第 2 步的对象元数据文件中添加了 name,则不需要此名称。

    如果您启用了跨域资源共享,则还应在此上传请求和后续上传请求中添加 Origin 标头。

    您可以向请求添加的可选标头包括 X-Upload-Content-TypeX-Upload-Content-Length

    如果成功,响应将包含 200 状态代码。

  4. 将响应的 Location 标头中提供的可续传会话 URI 保存到 POST Object 请求中。

    上传对象数据的后续请求会用到此 URI。

  1. 安装并初始化 gcloud CLI,以便为 Authorization 标头生成访问令牌。

  2. 使用 cURL,通过正文为空的 POST Object 请求调用 XML API

    curl -i -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" \
        -H "Content-Length: 0" \
        -H "Content-Type: OBJECT_CONTENT_TYPE" \
        -H "x-goog-resumable: start" \
        "https://storage.googleapis.com/BUCKET_NAME/OBJECT_NAME"

    其中:

    • OBJECT_CONTENT_TYPE 是该对象的内容类型,例如 image/png。如果您不指定内容类型,Cloud Storage 系统会将对象的 Content-Type 元数据设置为 application/octet-stream
    • BUCKET_NAME 是对象要上传到的存储桶的名称。例如 my-bucket
    • OBJECT_NAME 是您要为对象指定的网址编码名称。例如,pets/dog.png 的网址编码为 pets%2Fdog.png

    如果您启用了跨域资源共享,则还应在此上传请求和后续上传请求中添加 Origin 标头。

    如果成功,响应将包含 201 状态消息。

  3. 将响应的 Location 标头中提供的可续传会话 URI 保存到 POST Object 请求中。

    上传对象数据的后续请求会用到此 URI。

上传数据

启动可续传上传后,您可以通过以下两种方法上传对象的数据:

  • 在单个区块中:此方法通常具有最佳的效果,因为它需要较少的请求,因此具有更好的性能。
  • 在多个区块中:如果您需要减少单个请求中传输的数据量(例如,单个请求有固定时间限制时),或在上传开始时不了解上传操作的总大小。

单个区块上传

如需使用单个数据块上传数据,请执行以下操作:

  1. 使用 cURL,通过 PUT Object 请求调用 JSON API

    curl -i -X PUT --data-binary @OBJECT_LOCATION \
        -H "Content-Length: OBJECT_SIZE" \
        "SESSION_URI"

    其中:

    • OBJECT_LOCATION 是对象的本地路径。例如 Desktop/dog.png
    • OBJECT_SIZE 是对象中的字节数。例如 20000000
    • SESSION_URI 是您在启动可续传上传Location 标头中返回的值。

    或者,您可以添加前缀为 X-Goog-Meta- 的标头,以将对象的自定义元数据添加到此请求中。

  1. 使用 cURL,通过 PUT Object 请求调用 XML API

    curl -i -X PUT --data-binary @OBJECT_LOCATION \
        -H "Content-Length: OBJECT_SIZE" \
        "SESSION_URI"

    其中:

    • OBJECT_LOCATION 是对象的本地路径。例如 Desktop/dog.png
    • OBJECT_SIZE 是对象中的字节数。例如 20000000
    • SESSION_URI 是您在启动可续传上传Location 标头中返回的值。

如果上传全部完成,您会收到 200 OK201 Created 响应,以及与资源相关联的任何元数据。

如果上传请求中断或者您收到 5xx 响应,请按照恢复中断的上传中的步骤操作。

多个数据块上传

如需使用多个数据块上传数据,请执行以下操作:

  1. 根据您要上传的整体数据创建数据块。

    数据块的大小应该是 256 KiB(256 x 1024 字节)的整数倍,除非数据块是结束上传的最后一个数据块。较大的数据块大小通常可使上传速度更快,但请注意,速度和内存用量之间存在权衡。我们建议您使用至少 8 MiB 作为数据块大小。

  2. 使用 cURL,通过 PUT Object 请求调用 JSON API

    curl -i -X PUT --data-binary @CHUNK_LOCATION \
        -H "Content-Length: CHUNK_SIZE" \
        -H "Content-Range: bytes CHUNK_FIRST_BYTE-CHUNK_LAST_BYTE/TOTAL_OBJECT_SIZE" \
        "SESSION_URI"

    其中:

    • CHUNK_LOCATION 是您当前正在上传的数据块的本地路径。
    • CHUNK_SIZE 是您正在当前请求中上传的字节数。例如 8388608
    • CHUNK_FIRST_BYTE 是您正在上传的数据块包含的整个对象中的起始字节。
    • CHUNK_LAST_BYTE 是您正在上传的数据块包含的整个对象中的结束字节。
    • TOTAL_OBJECT_SIZE 是您正在上传的对象的总大小。
    • SESSION_URI 是您在启动可续传上传Location 标头中返回的值。

    Content-Range 的一个示例为 Content-Range: bytes 0-8388607/20000000。如需详细了解此标头,请参阅 Content-Range

    如果请求成功,服务器会返回 308 Resume Incomplete。响应包含 Range 标头

  3. 对您要上传的每个剩余数据块重复上述步骤,并使用每个响应的 Range 标头中包含的上限值来确定每个连续数据块的开始位置;您不应假定服务器已收到任何给定请求中发送的所有字节。

    (可选)在可续传上传的最终请求中,您可以添加前缀为 X-Goog-Meta- 的标头,以添加对象的自定义元数据。

  1. 根据您要上传的整体数据创建数据块。

    数据块的大小应该是 256 KiB(256 x 1024 字节)的整数倍,除非数据块是结束上传的最后一个数据块。较大的数据块大小通常可使上传速度更快,但请注意,速度和内存用量之间存在权衡。我们建议您使用至少 8 MiB 作为数据块大小。

  2. 使用 cURL,通过 PUT Object 请求调用 XML API

    curl -i -X PUT --data-binary @CHUNK_LOCATION \
        -H "Content-Length: CHUNK_SIZE" \
        -H "Content-Range: bytes CHUNK_FIRST_BYTE-CHUNK_LAST_BYTE/TOTAL_OBJECT_SIZE" \
        "SESSION_URI"

    其中:

    • CHUNK_LOCATION 是您当前正在上传的数据块的本地路径。
    • CHUNK_SIZE 是您正在当前请求中上传的字节数。例如 8388608
    • CHUNK_FIRST_BYTE 是您正在上传的数据块包含的整个对象中的起始字节。
    • CHUNK_LAST_BYTE 是您正在上传的数据块包含的整个对象中的结束字节。
    • TOTAL_OBJECT_SIZE 是您正在上传的对象的总大小。
    • SESSION_URI 是您在启动可续传上传Location 标头中返回的值。

    Content-Range 的一个示例为 Content-Range: bytes 0-8388607/20000000。如需详细了解此标头,请参阅 Content-Range

    如果请求成功,服务器会返回 308 Resume Incomplete。响应包含 Range 标头

  3. 对您要上传的每个剩余数据块重复上述步骤,并使用每个响应的 Range 标头中包含的上限值来确定每个连续数据块的开始位置;您不应假定服务器已收到任何给定请求中发送的所有字节。

上传全部完成后,您会收到 200 OK201 Created 响应,以及与资源相关联的任何元数据。

如有任何分块上传中断或者您收到 5xx 响应,您应完整地重新发送中断的分块,或者从中断的地方继续执行之前中断的上传

检查可续传上传的状态

如果您的可续传上传中断或者您不确定上传已完成,则可以检查上传的状态:

  1. 使用 cURL,通过 PUT Object 请求调用 JSON API

    curl -i -X PUT \
        -H "Content-Length: 0" \
        -H "Content-Range: bytes */OBJECT_SIZE" \
        "SESSION_URI"

    其中:

    • OBJECT_SIZE 是对象中的字节总数。如果您不知道对象的完整大小,请使用 * 作为此值。
    • SESSION_URI 是您在启动可续传上传Location 标头中返回的值。
  1. 使用 cURL,通过 PUT Object 请求调用 XML API

    curl -i -X PUT \
        -H "Content-Length: 0" \
        -H "Content-Range: bytes */OBJECT_SIZE" \
        "SESSION_URI"

    其中:

    • OBJECT_SIZE 是对象中的字节总数。如果您不知道对象的完整大小,请使用 * 作为此值。
    • SESSION_URI 是您在启动可续传上传Location 标头中返回的值。

200 OK201 Created 响应表明上传已完成,无需执行进一步操作。

308 Resume Incomplete 响应表明您需要继续上传数据。

  • 如果 Cloud Storage 尚未保留任何字节,则 308 响应没有 Range 标头。在这种情况下,您应从头开始上传。
  • 否则,308 响应具有 Range 标头,该标头表明 Cloud Storage 目前已保留哪些字节。在恢复中断的上传时,请使用此值。

恢复中断的上传

如果上传请求在收到响应之前被终止,或者您收到 503500 响应,则需要从中断的地方恢复中断的上传。如需恢复中断的上传,请执行以下操作:

  1. 检查您的可续传上传的状态

  2. 将响应中包含的 Range 标头的上限值保存到您的状态检查中。如果响应没有 Range 标头,则 Cloud Storage 尚未保留任何字节,您应从头开始上传

  3. 确保您要上传的对象数据从 Range 标头中的上限值后面的字节开始。

  4. 如果中断的请求包含前缀为 X-Goog-Meta- 的标头,请在请求中添加这些标头才能继续上传。

  5. 使用 cURL,通过 PUT Object 请求(该请求从 Range 标头中的值后面的字节开始上传数据)调用 JSON API

    curl -i -X PUT --data-binary @PARTIAL_OBJECT_LOCATION \
        -H "Content-Length: UPLOAD_SIZE_REMAINING" \
        -H "Content-Range: bytes NEXT_BYTE-LAST_BYTE/TOTAL_OBJECT_SIZE" \
        "SESSION_URI"

    其中:

    • PARTIAL_OBJECT_LOCATION 是您要上传的数据剩余部分的本地路径。
    • UPLOAD_SIZE_REMAINING 是您正在当前请求中上传的字节数。例如,如果总大小为 20000000 的对象在上传字节 0-42 后中断,则上传该对象剩余部分时的 UPLOAD_SIZE_REMAINING19999957
    • NEXT_BYTE 是您在第 2 步中保存的值后的下一个整数。例如,如果 42 是第 2 步中的上限值,则 NEXT_BYTE 的值为 43
    • LAST_BYTE 是此 PUT 请求中包含的结束字节。例如,为了上传完总大小为 20000000 的对象,LAST_BYTE 的值为 19999999
    • TOTAL_OBJECT_SIZE 是您正在上传的对象的总大小。例如 20000000
    • SESSION_URI 是您在启动可续传上传Location 标头中返回的值。
  1. 检查您的可续传上传的状态

  2. 将响应中包含的 Range 标头的上限值保存到您的状态检查中。如果响应没有 Range 标头,则 Cloud Storage 尚未保留任何字节,您应从头开始上传

  3. 确保您要上传的对象数据从 Range 标头中的上限值后面的字节开始。

  4. 使用 cURL,通过 PUT Object 请求(该请求从 Range 标头中的值后面的字节开始上传数据)调用 XML API

    curl -i -X PUT --data-binary @PARTIAL_OBJECT_LOCATION \
        -H "Content-Length: UPLOAD_SIZE_REMAINING" \
        -H "Content-Range: bytes NEXT_BYTE-LAST_BYTE/TOTAL_OBJECT_SIZE" \
        "SESSION_URI"

    其中:

    • PARTIAL_OBJECT_LOCATION 是您要上传的数据剩余部分的本地路径。
    • UPLOAD_SIZE_REMAINING 是您正在当前请求中上传的字节数。例如,如果总大小为 20000000 的对象在上传字节 0-42 后中断,则上传该对象剩余部分时的 UPLOAD_SIZE_REMAINING19999957
    • NEXT_BYTE 是您在第 2 步中保存的值后的下一个整数。例如,如果 42 是第 2 步中的上限值,则 NEXT_BYTE 的值为 43
    • LAST_BYTE 是此 PUT 请求中包含的结束字节。例如,为了上传完总大小为 20000000 的对象,LAST_BYTE 的值为 19999999
    • TOTAL_OBJECT_SIZE 是您正在上传的对象的总大小。例如 20000000
    • SESSION_URI 是您在启动可续传上传Location 标头中返回的值。

在会话 URI 处于活跃状态时,您可以根据需要多次恢复上传;会话 URI 的有效期为一周。数据上传成功后,Cloud Storage 会返回 200 OK201 created 状态代码。

取消上传

如需取消未完成的可续传上传并阻止任何进一步操作,请执行以下操作:

  1. 使用 cURL,通过 DELETE 请求调用 JSON API

    curl -i -X DELETE -H "Content-Length: 0" \
      "SESSION_URI"

    其中:

如果成功,响应将包含 499 状态代码。进一步尝试查询或恢复上传将导致 4xx 响应。

  1. 使用 cURL,通过 DELETE 请求调用 XML API

    curl -i -X DELETE -H "Content-Length: 0" \
      "SESSION_URI"

    其中:

如果成功,响应将包含 204 状态代码,未来尝试查询或恢复上传也会导致 204 响应。

失败处理

在极少数情况下,由于存储桶的权限发生了更改,或者对最终上传的对象进行完整性检查时检测到不匹配,因此请求恢复中断的上传可能会失败,并返回不可重试的“4xx”错误。如果发生这种情况,请通过启动新的可续传上传会话重试上传。

后续步骤