使用 JavaScript 或 jQuery 拆分文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12055386/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 15:11:24  来源:igfitidea点击:

Split file with JavaScript or jQuery

javascriptjqueryfileuploadsplit

提问by Sylnois

I need to upload a part of a file (only the first MB). I've created a PHP script which uploads the whole file. The data (formDataObject) is passed by a ajax call.

我需要上传文件的一部分(只有第一个 MB)。我创建了一个上传整个文件的 PHP 脚本。数据(formData对象)通过 ajax 调用传递。

My idea would be now to split the file with javascript (jquery). Is there any solution for my request?

我的想法是现在用 javascript (jquery) 拆分文件。我的要求有什么解决方案吗?

Current code:

当前代码:

function start(a){
    //var fSize = $('#fileUpload')[0].files[0].size / 1024;
    var formData = new FormData();    
    formData.append( 'fileUpload', $('#fileUpload')[0].files[0] );
    //AJAX
    $.ajax({
        url: 'script.php',
        type: 'POST',
        data: formData,
        processData: false,
        contentType: false,
        success: function(msg){
            alert("Win: " + msg);
        },
        error: function(bla, msg){
            alert("Fail: " + msg);
        }
    });
}

回答by MaxArt

Since you're using FormData, which is a fairly new technology, I'll show you something with new technologies as well.

由于您正在使用FormData,这是一项相当新的技术,因此我也会向您展示一些新技术。

First, read the file with a FileReaderobject:

首先,读取带有FileReader对象的文件:

var fr = new FileReader(), buf, file = $('#fileUpload')[0].files[0];
fr.onload = function(e) {
    buf = new Uint8Array(e.target.result);
};
fr.readAsArrayBuffer(file);

Then you can create a Blobfor each splitted part (1e6bytes long each):

然后你可以Blob为每个分割的部分(1e6每个字节长)创建一个:

for (var i = 0, blobs = []; i < buf.length; i += 1e6)
    blobs.push(new Blob([buf.subarray(i, i + 1e6)]));

Finally, you can add all your Blobs to your FormDataobject:

最后,您可以将所有Blobs添加到您的FormData对象中:

var formData = new FormData();
for (var i = 0; i < blobs.length; i++)
    formData.append("slice" + i, blobs[i], file.name + ".part" + i);

You should be ok. I haven't tested it, though.

你应该没问题。不过我还没有测试过。

I don't know anything about the performance either. You can use fr.readAsBinaryStringtoo, thus making e.target.resulta string. This way, you can create the Blobs using a simple substring/slice/substr/whatever, but I fear there could be some problems with Unicode characters and whatnot. Plus, maybe it's slower.

我也对表演一无所知。您也可以使用fr.readAsBinaryString,从而制作e.target.result一个字符串。这样一来,就可以创建Blob使用简单的小号substring/ slice/ substr/不管,但我担心可能会出现一些问题,Unicode字符和诸如此类的东西。另外,也许它更慢。

Putting everything in a more coherent snippet:

将所有内容放在一个更连贯的片段中:

$('#fileUpload').change(function() {
    // If no file is selected, there's nothing to do
    if (!this.files.length) return;

    var fr = new FileReader(), file = this.files[0];
    fr.onload = function(e) {
        splitAndSendFile(new Uint8Array(e.target.result), file);
    };
    fr.readAsArrayBuffer(file);
};

function splitAndSendFile(dataArray, file) {
    var i = 0, formData, blob;
    for (; i < dataArray.length; i += 1e6) {
        blob = new Blob([dataArray.subarray(i, i + 1e6)]);
        formData = new FormData();
        formData.append("fileUpload", blob, file.name + ".part" + (i / 1e6));
        $.ajax({
            url: 'script.php',
            type: 'POST',
            data: formData,
            processData: false,
            contentType: false,
            success: function(msg){
                alert("Win: " + msg);
            },
            error: function(bla, msg){
                alert("Fail: " + msg);
            }
        });
    }
}

Note: FormData.appendtakes a third optional parameter, which should be the name of the file in case of Fileor Blobvalues. If not specified, Blobs may get unpredictable random file names.

注意FormData.append采用第三个可选参数,如果是FileBlob值,它应该是文件的名称。如果未指定,Blobs 可能会获得不可预测的随机文件名。

Probably that parameter isn't standard, and it's not mentioned in the MDN artice, but I used it in the snippet above nonetheless. Anyway, if you know what you're doing, you can have several options to specify the file name. For example, with formData.append("filename", file.name)or sending a custom header in the request.

可能那个参数不是标准的,它在MDN 文章中没有提到,但我在上面的代码片段中使用了它。无论如何,如果您知道自己在做什么,则可以有多个选项来指定文件名。例如,formData.append("filename", file.name)在请求中使用或发送自定义标头。