I have the constraint of sending data to a server in JSON format only, and I need to send a PDF file together with other form data in the JSON. I though I could make a string from it with base64 like in this solution I found on 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), ...});
}
But it happened that reader.result
does not contain the whole PDF (whether I save it to file instead of sending, or get it back from the server). In a text editor the content is the same, but a binary editor says that some bytes are missing. My browser can load it as a pdf and the title shows, but the page is blank.
I also tried reader.readAsBinaryString
and transform to base64 myself with btoa
, but same result.
Edit: CodePen example: https://codepen.io/jdelafon/pen/eRWLdz?editors=1011
Edit: to verify, I did this:
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>
};
The body of the pdf is empty. If I replace file
by the original pdf
, it gets displayed entirely. So FileReader loses data in the process.
Is there a better way? Is it an encoding issue with FileReader
?
I also though about using FormData like this:
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), ...});
But now when I fetch the data back from the server, JS has no idea that it represents a FormData object, so I don't know how to get the file back for display in a browser. Is it possible?
The FileReader result property returns the file's contents. This property is only valid after the read operation is complete, and the format of the data depends on which of the methods was used to initiate the read operation.
You weren’t far from succeeding when you tried btoa
, except you can’t “btoa-ize” a 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 }),
});
}
I’m not sure why the readAsDataURL
solution failed though.
Edit: although not sure, it’s been suspected that the deprecated readAsBinaryString
method might be the source of the problem. The following solution, based on readAsDataURL
, is working:
reader.readAsDataURL(pdf);
reader.onload = () => {
$.ajax({
type: 'POST',
dataType: "json",
data: JSON.stringify({ "dataURL": reader.result }),
});
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With