Skip to content

https://juejin.cn/post/6844904046436843527#heading-19

  • 获取数组的最后一个元素: at(-1)

  • 数组与对象的相互转换

    对象到数组: Object.entries()
    数组到对象: Object.fromEntries()
    
  • 本地文件预览

    createObjectUrl

  • 文件秒传

    服务器已经存有一份了,不需要再次上传。这个文件的文件名由文件内容hash而成。

    需要服务器提供一个接口,返回已经上传的分片和大小。

  • 切片上传

    1.获取arrayBuffer : blob.arrayBuffer() 或者 fileReader.readAsArrayBuffer()

    利用浏览器提供的web cryptography api, 它用于计算传入数据的sha-256 算法。

    2.计算哈希:await crypto.subtle.digest('SHA-256',arrayBuffer)

    计算文件内容的hash会很慢,可以用worker,防止耗时操作阻塞UI线程

    3.得到文件名之后,就可以处理切片了

  • 切片数量的动态调整

  • content-type的application/octet-stream 和 form-data区别

    用字节流的话只能上传二进制文件

    如果用formData的话可以同时上传文件和普通字段

  • 并行写入

    利用可写流可以指定写入位置

image-20231213002423074

  • 暂停上传

    控制上传的状态:未上传,上传中,已暂停

    存放所有上传请求的cancel token

    调用cancel方法,axios会抛出错误,在try catch里面用isCancel方法判断是否为用户取消暂停的而导致的异常

  • 恢复上传(即断点续传)

    服务端需要提供一个接口,获取每个分片上传了多少,以便客户端上传分片剩下的部分

    const remainingChunk = file.slice(uploadedSize)

    如果remainingChunk.size==0 则表示已经上传完成,直接resolve即可

​ 断点续传还需要给接口传 分片的起始索引,用于服务端给分片的写入位置

  • worker

    与主线程隔离,有自己的全局上下文,不能访问dom, window

  • 控制并发上传的数量

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>File Upload Demo</title>
    </head>
    <body>
    
    <input type="file" id="fileInput" />
    <button onclick="startUpload()">Start Upload</button>
    
    <script>
    // Mock function to simulate uploading a file chunk
    function uploadChunk(chunk) {
      return new Promise(resolve => {
        // Simulate asynchronous upload
        setTimeout(() => {
          console.log(`Uploaded chunk: ${chunk}`);
          resolve();
        }, Math.random() * 1000); // Simulating network latency
      });
    }
    
    // Function to handle file upload
    async function startUpload() {
      const fileInput = document.getElementById('fileInput');
      const file = fileInput.files[0];
    
      const chunkSize = 1024 * 1024; // 1 MB chunk size
      const totalChunks = Math.ceil(file.size / chunkSize);
      const concurrencyLimit = 5; // Maximum concurrent uploads
    
      let uploadedChunks = 0;
    
      async function uploadNextChunk() {
        if (uploadedChunks >= totalChunks) {
          console.log('Upload completed');
          return;
        }
    
        const start = currentChunk * chunkSize;
        const end = Math.min((currentChunk + 1) * chunkSize, file.size);
        const chunk = file.slice(start, end);
    
        console.log(`Uploading chunk ${currentChunk + 1}/${totalChunks}`);
    
        // Simulate upload and wait for it to complete
        await uploadChunk(chunk);
    
        uploadedChunks++;
        // Upload the next chunk
        uploadNextChunk();
      }
    
      // Start initial uploads (up to the concurrency limit)
      const initialUploads = Math.min(totalChunks, concurrencyLimit);
      for (let i = 0; i < initialUploads; i++) {
        uploadNextChunk();
      }
    }
    
    </script>
    
    </body>
    </html>