【问题标题】:Split an uploaded file into multiple chunks using javascript使用 javascript 将上传的文件拆分为多个块
【发布时间】:2020-09-17 23:42:43
【问题描述】:

我正在寻找一种方法来拆分浏览器前端的任何文本/数据文件,然后再将其上传为多个文件。我的限制是每次上传 40KB。因此,如果用户上传一个 400KB 的文件,它会在前端将该文件拆分为 10 个单独的块或 10 个单独的文件,然后再将其上传到服务器。

目前,我正在通过将此文件转换为 base64 格式的字符串,然后将此字符串拆分为 40KB,得到 10 个单独的块。从那里我上传每个块,文件名为 chunk-1-of-10, chunk-2-of-10...

当提取这些文件时,我只是将所有这些块连接回来并将其从 base64 反转换为它的文件格式。

有没有更好的方法来做到这一点?是否有一个库可以处理所有这些而不是从头开始编写它?我不确定 base64 路由是否是最好的方法。

【问题讨论】:

    标签: javascript google-chrome base64 compression frontend


    【解决方案1】:

    无需使用 FileReader 将内容读入 ram 使用 base64 只会增加您需要上传的内容的大小,base64 占用的大小增加了约 33%

    使用Blob.slice 获取块

    // simulate a file from a input
    const file = new File(['a'.repeat(1000000)], 'test.txt')
    
    const chunkSize = 40000
    const url = 'https://httpbin.org/post'
    
    for (let start = 0; start < file.size; start += chunkSize) {
      const chunk = file.slice(start, start + chunkSize + 1)
      const fd = new FormData()
      fd.set('data', chunk)
      
      await fetch(url, { method: 'post', body: fd }).then(res => res.text())
    }
    

    【讨论】:

    • 感谢您的解决方案!对此的一个快速补充是将“start”添加到 slice() 的第二个参数以获取后续块。 const chunk = file.slice(start, start + chunkSize + 1).
    • 我们将如何输出服务器响应?
    • @ParsaYazdani console.log(await fetch(url, {method: 'post', body: fd}).then(res =&gt; res.text()))
    • 这对我们有用,但是,我们必须做一个小调整,删除块计算中的 +1:const chunk = file.slice(start, start + chunkSize)
    • 是否需要遍历每个chunk并发出多个http请求?不能使用文件读取流来完成吗?
    【解决方案2】:

    您可以避免使用 FileReader 进行 base64 编码,然后以二进制形式发送:

    const url = 'http://www.example.com/upload';
    
    document.getElementById('file-uploader').addEventListener('change', function(e) {
        const size = 40000;
        var reader = new FileReader();
        var buf;
        var file = document.getElementById('file-uploader').files[0];
        reader.onload = function(e) {
            buf = new Uint8Array(e.target.result);
            for (var i = 0;  i < buf.length; i += size) {
                var fd = new FormData();
                fd.append('fname', [file.name, i+1, 'of', buf.length].join('-'));
                fd.append('data', new Blob([buf.subarray(i, i + size)]));
                var oReq = new XMLHttpRequest();
                oReq.open("POST", url, true);
                oReq.onload = function (oEvent) {
                   // Uploaded.
                };
                oReq.send(fd);
            }
        }
          
        reader.readAsArrayBuffer(file);
    });
    &lt;input type="file" id="file-uploader"/&gt;

    【讨论】:

    • 我们将如何输出服务器响应?
    • 是否需要遍历每个chunk并发出多个http请求?不能使用文件读取流来完成吗?
    猜你喜欢
    • 2015-12-30
    • 2013-01-23
    • 1970-01-01
    • 1970-01-01
    • 2017-02-27
    • 1970-01-01
    • 2012-11-10
    • 2017-01-02
    相关资源
    最近更新 更多