使用 JavaScript 或 jQuery 拆分文件

Posted

技术标签:

【中文标题】使用 JavaScript 或 jQuery 拆分文件【英文标题】:Split file with JavaScript or jQuery 【发布时间】:2012-08-16 19:54:36 【问题描述】:

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

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

当前代码:

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);
        
    );

【问题讨论】:

您无权访问 JavaScript 中的内容文件。没有办法拆分它。顺便说一句,也无法使用 AJAX 发布文件。 @RoToRa 你为什么不把它作为答案发布? @RoToRa 好吧,实际上有一种方法 - 使用新的FileReader API。但不知何故,我认为这与这里无关。 ) @user1515190 我想this article 可能对你有帮助。但请注意,其中使用的工具尚未得到普遍支持……。 @RoToRa ehm,上面的脚本有效。 【参考方案1】:

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

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

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

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

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

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

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

你应该没事的。不过我还没有测试过。

我也对表演一无所知。您也可以使用fr.readAsBinaryString,从而使e.target.result 成为一个字符串。这样,您可以使用简单的substring/slice/substr/whatever 创建Blobs,但我担心 Unicode 字符之类的可能会出现一些问题。另外,也许它更慢。

将所有内容放在一个更连贯的 sn-p 中:

$('#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);
            
        );
    

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

可能这个参数不是标准的,在MDN artice中也没有提到,但我还是在上面的sn-p中使用了它。无论如何,如果你知道你在做什么,你可以有几个选项来指定文件名。例如,使用formData.append("filename", file.name) 或在请求中发送自定义标头。

【讨论】:

感谢您的回复。我不想发送整个数组,只是部分发送(所以我可以控制进度条),但不知何故它不起作用(最后链接到我的脚本)。我的 PHP 脚本是一个简单的命令(move_uploaded_file($_FILES["fileUpload"]["tmp_name"], $uploadPath . $_FILES["fileUpload"]["name"]);)。我想在服务器端将零件组装在一起。 193.109.52.60/dario/f @user1515190 由于blob.push(... 行中的语法错误,它不起作用。错过了一个右括号,我的错。你可以再试一次。 仍然无法正常工作:/ PS:非常感谢您的帮助!我尝试了几个星期(当然不是全职:D) @user1515190 啊,我明白了。现在问题出在 您的 代码中。我没有把所有的东西都放在一个完整的形式中,但它不能以同步的方式完成。我会在答案中给你一个提示。 还是有些不对劲。我试图用警报调试我的代码。警报 6 不出现(在此代码部分之后:blob = new Blob([dataArray.subarray(i, i + 1e6)]);

以上是关于使用 JavaScript 或 jQuery 拆分文件的主要内容,如果未能解决你的问题,请参考以下文章

如何使用JavaScript将长数组拆分为更小的数组

Javascript / Jquery 将变量拆分为两个以进行条带集成

如何在 javascript/jquery 中拆分字符串并测试字符串的开头? [复制]

Javascript如何拆分()多个字符串或值? [关闭]

将数组拆分为多个数组或备用 - Javascript

如何在 C# 或 JavaScript 中将 DN 拆分并加入到来自 Active Directory 对象的路径