我有一个示例,用户可以从中选择一个文件(尤其是 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);
}
现在假设我使用的是 reader.readAsText(file);
而不是 reader.readAsArrayBuffer(file);
。在那种情况下,我会将文本转换为数组缓冲区并尝试做同样的事情。
$(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);
}
Now if I passed a PDF file that is small in size and only has text, this would work file, but when selecting files that are large and/or has images in them, a currputed file will be downloaded.
现在我知道我正在努力让自己的生活更艰难。但我想做的是以某种方式将 readAsText()
的结果转换为 arrayBuffer,以便 readAsText()
和 readAsArrayBuffer()
工作相同。
最佳答案
readAsText
method不只是使字节在 UCS-16 字符串中可访问。相反,它根据给定的文本编码格式(默认为 UTF-8)将它们解码为文本。这会弄乱您尝试读取的任何二进制数据。正如您已经想到的那样,为此使用 readAsArrayBuffer
。
您可以尝试使用TextEncoder
来encode
您的文本返回到类型化数组,但这并不能保证产生相同的结果:BOM 被剥离,无效的 UTF-8 序列导致错误,如果您不走运,那么甚至会发生 Unicode 规范化。
如果您明确指定单字节解码可能会更容易,但实际上您应该只使用 readAsArrayBuffer
。
关于javascript - 数组缓冲区的文本导致文件损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55691669/