文件到阵列缓冲区会导致文件损坏

问题描述 投票:8回答:3

我有一个示例,用户可以从中选择文件(特别是PDF文件),将该文件转换为数组缓冲区,从该数组缓冲区构造文件并下载该文件。按预期工作。

<input type="file" id="file_input" class="foo" />
<div id="output_field" class="foo"></div>


$(document).ready(function(){
    $('#file_input').on('change', function(e){
        readFile(this.files[0], function(e) {
            //manipulate with result...
            $('#output_field').text(e.target.result);
            try {           
            var file = new Blob([e.target.result], { type: 'application/pdf' });
            var fileURL = window.URL.createObjectURL(file);
            var seconds = new Date().getTime() / 1000;
            var fileName = "cert" + parseInt(seconds) + ".pdf";
            var a = document.createElement("a");
            document.body.appendChild(a);
            a.style = "display: none";
            a.href = fileURL;
            a.download = fileName;
            a.click();
             }
            catch (err){
            $('#output_field').text(err);
            }
        });     
    });
});

function readFile(file, callback){
    var reader = new FileReader();
    reader.onload = callback
    reader.readAsArrayBuffer(file);
}

现在让我们说我使用qazxsw poi而不是qazxsw poi。在那种情况下,我会将文本转换为数组缓冲区并尝试做同样的事情。

reader.readAsText(file);

现在,如果我传递的文件很小并且只有文本,那么这将是工作文件,但是当选择大文件和/或包含图像的文件时,将下载一个currputed文件。

现在我知道我正试图让自己的生活变得更加艰难。但我想要做的是以某种方式将结果从reader.readAsArrayBuffer(file);转换为arrayBuffer,以便$(document).ready(function(){ $('#file_input').on('change', function(e){ readFile(this.files[0], function(e) { //manipulate with result... try { var buf = new ArrayBuffer(e.target.result.length * 2); var bufView = new Uint16Array(buf); for (var i=0, strLen = e.target.result.length; i<strLen; i++) { bufView[i] = e.target.result.charCodeAt(i); } var file = new Blob([bufView], { type: 'application/pdf' }); var fileURL = window.URL.createObjectURL(file); var seconds = new Date().getTime() / 1000; var fileName = "cert" + parseInt(seconds) + ".pdf"; var a = document.createElement("a"); document.body.appendChild(a); a.style = "display: none"; a.href = fileURL; a.download = fileName; a.click(); } catch (err){ $('#output_field').text(err); } }); }); }); function readFile(file, callback){ var reader = new FileReader(); reader.onload = callback reader.readAsText(file); } readAsText()同时工作。

javascript html filereader
3个回答
3
投票

readAsText()不会简单地在UCS-16字符串中访问字节。相反,它根据给定的文本编码格式将它们解码为文本,默认为UTF-8。这将弄乱您尝试阅读的任何二进制数据。正如你已经想到的那样,使用readAsArrayBuffer()

你可以尝试使用readAsText methodreadAsArrayBuffer你的文本回到一个类型化的数组,但是不能保证产生相同的结果:BOM被剥离,无效的UTF-8序列导致错误,如果你不幸,那么甚至是Unicode正常化将会发生。

如果明确指定单字节解码可能会更容易,但实际上你应该只使用TextEncoder


1
投票

正如encode已经回答的那样,你应该使用readAsArrayBuffer代替Bergi,因为后者解码字节序列,默认为UTF-8。

UTF-8是可变长度编码,其中字符可以在1到4个字节之间。在非UTF-8的二进制数据上运行解码器将无法恢复,从而破坏二进制数据。

例如,只逐字复制0x00-0x7F。 0xC2至0xDF是2字节序列的起始序列,3字节序列的0xE0至0xEF和4字节序列的0xF0至0xFF。 0x80到0xBF是序列的一部分。

以下是它如何被破坏的几个例子(节点12.1):

readAsArrayBuffer

0xFFFD是无法将输入转换为已知代码点时使用的替换字符。


-1
投票

这可能是我很久以前遇到的图形文件。由于某种原因,二进制文件具有特定的格式,而像cr / lf这样的东西在他们自己的位置可能是合法的。通过将二进制文件作为文本读取并将其写回,实际上每行可以输入额外的cr / lf,从而丢弃文件中的原始格式/内容/指针。

为了确认这一点,我将你的原始文件,读/写为数组缓冲区到一个Test文件,然后用文本的读/写做同样的事情到SecondTest文件。然后在两个文件之间进行二进制比较。

我敢打赌你无意中在那里得到了额外的东西。

© www.soinside.com 2019 - 2024. All rights reserved.