FileReader 在阅读 PDF 时丢失数据
FileReader losing data when reading PDF
我只能以 JSON 格式向服务器发送数据,我需要将 PDF 文件与 JSON 中的其他表单数据一起发送。我虽然可以用 base64 从它制作一个字符串,就像在 this solution 我在 SO:
中找到的那样
let data = {foo: 1, bar: 2};
let reader = new FileReader();
reader.readAsDataURL(pdf);
reader.onload = () => {
data.file = reader.result;
$.ajax({type: 'POST', dataType: "json", data: JSON.stringify(data), ...});
}
但碰巧 reader.result
不包含整个 PDF(无论我是将其保存到文件而不是发送,还是从服务器取回)。在文本编辑器中内容是相同的,但是二进制编辑器说缺少一些字节。我的浏览器可以将其加载为 pdf 并显示标题,但页面是空白的。
我也试过 reader.readAsBinaryString
并自己用 btoa
转换为 base64,但结果相同。
编辑:CodePen 示例:https://codepen.io/jdelafon/pen/eRWLdz?editors=1011
编辑:为了验证,我这样做了:
let reader = new FileReader();
reader.readAsBinaryString(pdf);
reader.onload = () => {
let blob = reader.result;
let file = new Blob([blob], {type: 'application/pdf'});
let fileURL = window.URL.createObjectURL(file);
// make it display in <embed>
};
pdf的body为空。如果我用原来的 pdf
替换 file
,它就会完整显示。所以FileReader在这个过程中丢失了数据。
有没有更好的方法?是 FileReader
的编码问题吗?
我也想像这样使用 FormData:
let data = {foo: 1, bar: 2};
let fd = new FormData();
fd.append('file', pdf);
data.file = btoa(fd);
$.ajax({type: 'POST', dataType: "json", data: JSON.stringify(data), ...});
但是现在当我从服务器取回数据时,JS不知道它代表一个FormData object,所以我不知道如何取回文件以在浏览器中显示。可能吗?
当您尝试 btoa
时,您离成功不远了,只是您不能“btoa-ize”一个 FormData。
reader.readAsBinaryString(pdf); // don’t use this! See edit below
reader.onload = () => {
let b64payload = btoa(reader.result);
$.ajax({
type: 'POST',
dataType: "json",
data: JSON.stringify({ "file": b64payload }),
});
}
我不确定为什么 readAsDataURL
解决方案失败了。
编辑: 虽然不确定,但怀疑已弃用的 readAsBinaryString
方法可能是问题的根源。以下基于 readAsDataURL
的解决方案正在运行:
reader.readAsDataURL(pdf);
reader.onload = () => {
$.ajax({
type: 'POST',
dataType: "json",
data: JSON.stringify({ "dataURL": reader.result }),
});
};
没有添加 Watilin 的答案,所以这里是从 Codepen 复制的工作片段:
function onUpload(input) {
let originalFile = input.files[0];
let reader = new FileReader();
reader.readAsDataURL(originalFile);
reader.onload = () => {
let json = JSON.stringify({ dataURL: reader.result });
// View the file
let fileURL = JSON.parse(json).dataURL;
$("#display-pdf").empty();
$("#display-pdf").append(`<object data="${fileURL}"
type="application/pdf" width="400px" height="200px">
</object>`);
// View the original file
let originalFileURL = URL.createObjectURL(originalFile);
$("#display-pdf").append(`<object data="${originalFileURL}"
type="application/pdf" width="400px" height="200px">
</object>`)
.onload(() => {
URL.revokeObjectURL(originalFileURL);
});
};
}
HTML:
<input id="file-input" type="file" onchange="onUpload(this)" />
<div id="display-pdf"></div>
我只能以 JSON 格式向服务器发送数据,我需要将 PDF 文件与 JSON 中的其他表单数据一起发送。我虽然可以用 base64 从它制作一个字符串,就像在 this solution 我在 SO:
中找到的那样let data = {foo: 1, bar: 2};
let reader = new FileReader();
reader.readAsDataURL(pdf);
reader.onload = () => {
data.file = reader.result;
$.ajax({type: 'POST', dataType: "json", data: JSON.stringify(data), ...});
}
但碰巧 reader.result
不包含整个 PDF(无论我是将其保存到文件而不是发送,还是从服务器取回)。在文本编辑器中内容是相同的,但是二进制编辑器说缺少一些字节。我的浏览器可以将其加载为 pdf 并显示标题,但页面是空白的。
我也试过 reader.readAsBinaryString
并自己用 btoa
转换为 base64,但结果相同。
编辑:CodePen 示例:https://codepen.io/jdelafon/pen/eRWLdz?editors=1011
编辑:为了验证,我这样做了:
let reader = new FileReader();
reader.readAsBinaryString(pdf);
reader.onload = () => {
let blob = reader.result;
let file = new Blob([blob], {type: 'application/pdf'});
let fileURL = window.URL.createObjectURL(file);
// make it display in <embed>
};
pdf的body为空。如果我用原来的 pdf
替换 file
,它就会完整显示。所以FileReader在这个过程中丢失了数据。
有没有更好的方法?是 FileReader
的编码问题吗?
我也想像这样使用 FormData:
let data = {foo: 1, bar: 2};
let fd = new FormData();
fd.append('file', pdf);
data.file = btoa(fd);
$.ajax({type: 'POST', dataType: "json", data: JSON.stringify(data), ...});
但是现在当我从服务器取回数据时,JS不知道它代表一个FormData object,所以我不知道如何取回文件以在浏览器中显示。可能吗?
当您尝试 btoa
时,您离成功不远了,只是您不能“btoa-ize”一个 FormData。
reader.readAsBinaryString(pdf); // don’t use this! See edit below
reader.onload = () => {
let b64payload = btoa(reader.result);
$.ajax({
type: 'POST',
dataType: "json",
data: JSON.stringify({ "file": b64payload }),
});
}
我不确定为什么 readAsDataURL
解决方案失败了。
编辑: 虽然不确定,但怀疑已弃用的 readAsBinaryString
方法可能是问题的根源。以下基于 readAsDataURL
的解决方案正在运行:
reader.readAsDataURL(pdf);
reader.onload = () => {
$.ajax({
type: 'POST',
dataType: "json",
data: JSON.stringify({ "dataURL": reader.result }),
});
};
没有添加 Watilin 的答案,所以这里是从 Codepen 复制的工作片段:
function onUpload(input) {
let originalFile = input.files[0];
let reader = new FileReader();
reader.readAsDataURL(originalFile);
reader.onload = () => {
let json = JSON.stringify({ dataURL: reader.result });
// View the file
let fileURL = JSON.parse(json).dataURL;
$("#display-pdf").empty();
$("#display-pdf").append(`<object data="${fileURL}"
type="application/pdf" width="400px" height="200px">
</object>`);
// View the original file
let originalFileURL = URL.createObjectURL(originalFile);
$("#display-pdf").append(`<object data="${originalFileURL}"
type="application/pdf" width="400px" height="200px">
</object>`)
.onload(() => {
URL.revokeObjectURL(originalFileURL);
});
};
}
HTML:
<input id="file-input" type="file" onchange="onUpload(this)" />
<div id="display-pdf"></div>