Browser.js分片上传

OSS提供的分片上传(MultipartUpload)功能,将要上传的较大文件(Object)分成多个分片(Part)来分别上传,上传完成后再调用CompleteMultipartUpload接口将这些Part组合成一个Object来达到断点续传的效果。

注意事项

  • 在分片上传之前,请确保您已了解该功能。更多信息,请参见分片上传

  • 当您使用webpack或browserify等打包工具时,请通过npm install ali-oss的方式安装Browser.js SDK。

  • 通过浏览器访问OSS时涉及跨域请求,如果未设置跨域规则,浏览器会拒绝跨域访问请求。如果您希望通过浏览器可以正常访问OSS,需要通过OSS设置跨域规则。具体操作,请参见准备工作

  • 由于Browser.js SDK通常在浏览器环境下使用,为避免暴露阿里云账号访问密钥(AccessKey ID和AccessKey Secret),强烈建议您使用临时访问凭证的方式执行OSS相关操作。

    临时访问凭证包括临时访问密钥(AccessKey ID和AccessKey Secret)和安全令牌(SecurityToken)。获取临时访问凭证的具体操作,请参见授权访问

分片上传完整示例代码

当需要上传的文件大小较大时,您可以通过MultipartUpload接口进行分片上传。分片上传是指将要上传的文件分成多个数据块(Part)来分别上传。当其中一些分片上传失败后,OSS将保留上传进度记录,再次重传时只需要上传失败的分片,而不需要重新上传整个文件。

重要

通常在文件大于100 MB的情况下,建议采用分片上传的方法,通过断点续传和重试,提高上传成功率。如果在文件小于100 MB的情况下使用分片上传,且partSize设置不合理的情况下,可能会出现无法完整显示上传进度的情况。对于小于100 MB的文件,建议使用简单上传的方式。

以下代码以分片上传的方式将文件上传至examplebucket下的exampleobject.txt文件。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
  </head>

  <body>
    <button id="submit">上传</button>
    <input id="file" type="file" />
    <!--导入sdk文件-->
    <script
      type="text/javascript"
      src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.18.0.min.js"
    ></script>
    <script type="text/javascript">
      const client = new OSS({
        // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
        region: "yourRegion",
        authorizationV4: true,
        // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
        accessKeyId: "yourAccessKeyId",
        accessKeySecret: "yourAccessKeySecret",
        // 从STS服务获取的安全令牌(SecurityToken)。
        stsToken: "yourSecurityToken",
        // 填写Bucket名称,例如examplebucket。
        bucket: "examplebucket",
      });

      const headers = {
        // 指定该Object被下载时的网页缓存行为。
        "Cache-Control": "no-cache",
        // 指定该Object被下载时的名称。
        "Content-Disposition": "example.txt",
        // 指定该Object被下载时的内容编码格式。
        "Content-Encoding": "utf-8",
        // 指定过期时间,单位为毫秒。
        Expires: "1000",
        // 指定Object的存储类型。
        "x-oss-storage-class": "Standard",
        // 指定Object标签,可同时设置多个标签。
        "x-oss-tagging": "Tag1=1&Tag2=2",
        // 指定初始化分片上传时是否覆盖同名Object。此处设置为true,表示禁止覆盖同名Object。
        "x-oss-forbid-overwrite": "true",
      };

      // 指定上传到examplebucket的Object名称,例如exampleobject.txt。
      const name = "exampleobject.txt";
      // 获取DOM。
      const submit = document.getElementById("submit");
      const options = {
        // 获取分片上传进度、断点和返回值。
        progress: (p, cpt, res) => {
          console.log(p);
        },
        // 设置并发上传的分片数量。
        parallel: 4,
        // 设置分片大小。默认值为1 MB,最小值为100 KB。
        partSize: 1024 * 1024,
        // headers,
        // 自定义元数据,通过HeadObject接口可以获取Object的元数据。
        meta: { year: 2020, people: "test" },
        mime: "text/plain",
      };

      // 监听按钮。
      submit.addEventListener("click", async () => {
        try {
          const data = document.getElementById("file").files[0];
          // 分片上传。
          const res = await client.multipartUpload(name, data, {
            ...options,
            // 设置上传回调。
            // 如果不涉及回调服务器,请删除callback相关设置。
            callback: {
              // 设置回调请求的服务器地址。
              url: "http://examplebucket.aliyuncs.com:23450",
              // 设置回调请求消息头中Host的值,即您的服务器配置Host的值。
              host: "yourHost",
              /* eslint no-template-curly-in-string: [0] */
              // 设置发起回调时请求body的值。
              body: "bucket=${bucket}&object=${object}&var1=${x:var1}",
              // 设置发起回调请求的Content-Type。
              contentType: "application/x-www-form-urlencoded",
              customValue: {
                // 设置发起回调请求的自定义参数。
                var1: "value1",
                var2: "value2",
              },
            },
          });
          console.log(res);
        } catch (err) {
          console.log(err);
        }
      });
    </script>
  </body>
</html>

在使用MultipartUpload接口时,如果遇到ConnectionTimeoutError超时问题,业务方需自行处理超时逻辑。例如通过缩小分片大小、增加超时时间、重试请求或者捕获ConnectionTimeoutError错误等方法处理超时。更多信息,请参见网络错误处理

取消分片上传事件

您可以调用client.abortMultipartUpload方法来取消分片上传事件。当一个分片上传事件被取消后,无法再使用该uploadId进行任何操作,已上传的分片数据会被删除。

以下代码用于取消分片上传事件:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
  </head>

  <body>
    <button id="submit">上传</button>
    <button id="abort">中断</button>
    <!--导入sdk文件-->
    <script
      type="text/javascript"
      src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.18.0.min.js"
    ></script>
    <script type="text/javascript">
      const client = new OSS({
        // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
        region: "yourRegion",
        authorizationV4: true,
        // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
        accessKeyId: "yourAccessKeyId",
        accessKeySecret: "yourAccessKeySecret",
        // 从STS服务获取的安全令牌(SecurityToken)。
        stsToken: "yourSecurityToken",
        // 填写Bucket名称,例如examplebucket。
        bucket: "examplebucket",
      });
      // 生成用于分片上传的100 MB大小的文件。
      const fileContent = Array(1024 * 1024 * 100)
        .fill("a")
        .join("");
      const file = new File([fileContent], "multipart-upload-file");
      // 设置上传到examplebucket的Object名称,例如exampleobject.txt。
      const name = "exampleobject.txt";
      // 设置中断点。
      let abortCheckpoint;
      // 获取DOM。
      const submit = document.getElementById("submit");
      const abort = document.getElementById("abort");

      // 监听上传按钮,单击“上传”后开始分片上传。
      submit.addEventListener("click", async () => {
        try {
          const res = await client.multipartUpload(name, file, {
            progress: (p, cpt, res) => {
              // 为中断点赋值。
              abortCheckpoint = cpt;
              // 获取上传进度。
              console.log(p);
            },
          });
        } catch (err) {
          console.log(err);
        }
      });
      // 监听中断按钮。
      abort.addEventListener("click", () => {
        // 中断分片上传。
        client.abortMultipartUpload(
          abortCheckpoint.name,
          abortCheckpoint.uploadId
        );
      });
    </script>
  </body>
</html>

列举已上传的分片

调用client.listParts方法列举出指定uploadId下所有已经上传成功的分片。

以下代码用于列举已上传的分片:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
  </head>

  <body>
    <button id="submit">上传</button>
    <button id="check">列举已上传的分片</button>
    <!--导入sdk文件-->
    <script
      type="text/javascript"
      src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.18.0.min.js"
    ></script>
    <script type="text/javascript">
      const client = new OSS({
         // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
         region: 'yourRegion',
         authorizationV4: true,
         // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
         accessKeyId: 'yourAccessKeyId',
         accessKeySecret: 'yourAccessKeySecret',
         // 从STS服务获取的安全令牌(SecurityToken)。
        stsToken: 'yourSecurityToken',
        // 填写Bucket名称,例如examplebucket。
        bucket: "examplebucket",
      });
      // 生成用于分片上传的100 MB大小的文件。
      const fileContent = Array(1024 * 1024 * 100)
        .fill("a")
        .join("");
      const file = new File([fileContent], "multipart-upload-file");
      // 设置上传到examplebucket的Object名称,例如exampleobject.txt。
      const name = "exampleobject.txt";
      // 设置中断点。
      let abortCheckpoint;

      // 获取DOM。
      const submit = document.getElementById("submit");
      const check = document.getElementById("check");

      // 监听按钮。
      submit.addEventListener("click", async () => {
        try {
          const res = await client.multipartUpload(name, file, {
            progress: (p, cpt, res) => {
              // 为中断点赋值。
              abortCheckpoint = cpt;
              // 获取上传进度。
              console.log("progress=====", p);
            },
          });
        } catch (err) {
          console.log(err);
        }
      });
      // 监听按钮。
      check.addEventListener("click", async () => {
        // 列举已上传的分片。
        const result = await client.listParts(name, abortCheckpoint.uploadId);
        console.log(result);
      });
    </script>
  </body>
</html>

列举分片上传事件

调用client.listUploads方法列举出所有执行中的分片上传事件,即已初始化但尚未完成或已取消的分片上传事件。

以下代码用于列举分片上传事件:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
  </head>

  <body>
    <button id="check">列举分片上传事件</button>
    <!--导入sdk文件-->
    <script
      type="text/javascript"
      src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.18.0.min.js"
    ></script>
    <script type="text/javascript">
      const client = new OSS({
         // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
         region: 'yourRegion',
         authorizationV4: true,
         // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
         accessKeyId: 'yourAccessKeyId',
         accessKeySecret: 'yourAccessKeySecret',
         // 从STS服务获取的安全令牌(SecurityToken)。
        stsToken: 'yourSecurityToken',
        // 填写Bucket名称,例如examplebucket。
        bucket: "examplebucket",
      });
      // 获取DOM。
      const check = document.getElementById("check");

      // 监听按钮。
      check.addEventListener("click", async () => {
        // 获取所有已初始化但尚未完成或已取消的分片上传事件。
        const result = await client.listUploads({ "max-uploads": 100 });
        console.log("uploads", result.uploads);
      });
    </script>
  </body>
</html>

相关文档

  • 关于分片上传的完整示例代码,请参见GitHub示例

  • Browser.js SDK分片上传调用的方法multipartUpload中封装了三个API接口,详情如下:

  • 关于取消分片上传事件的API接口说明,请参见AbortMultipartUpload

  • 关于列举已上传分片的API接口说明,请参见ListParts

  • 关于列举所有执行中的分片上传事件(即已初始化但尚未完成或已取消的分片上传事件)的API接口说明,请参见ListMultipartUploads

常见问题

报错PLease set the etag of expose-headers in Oss.如何处理?

  • 问题原因

    未正确设置跨域。

  • 解决方法

    您需要为当前Bucket设置跨域。设置跨域规则时需要暴露常见Header(x-oss-request-idETag)。具体步骤,请参见跨域设置

报错The operation is not supported for this resource.如何处理?

  • 问题原因

    您在调用CompleteMultipartUpload接口时设置了Object存储类型。

  • 解决方法

    不支持在分片上传过程中调用CompleteMultipartUpload时设置Object存储类型。如果您需要在分片上传过程中指定Object存储类型,您需要在调用InitiateMultipartUpload时进行设置。