The following code works as expected. Open the page "https://wiki.epfl.ch/" on Google Chrome, and execute this code on the Developer console. Note: the page "https://wiki.epfl.ch/test.php" does not exists and so it fails to load, but that's not the issue.
response = await fetch("https://wiki.epfl.ch/lapa-studio/documents/DTS/laser%20tutorial.pdf");
response.text().then(function(content) {
formData = new FormData();
console.log(content.length);
console.log(content);
formData.append("content", content);
fetch("https://wiki.epfl.ch/test.php", {method: 'POST', body: formData});
})
It logs:
content.length: 57234
content: %PDF-1.3
%���������
4 0 obj
<< /Length 5 0 R /Filter /FlateDecode >>
stream
x��K��F�����;¢�
...
Go to the Developer Network tab, choose the 'test.php' page, navigate to "Requested payload:" and you can see this content:
------WebKitFormBoundaryOJOOGb7N43BxCRlv
Content-Disposition: form-data; name="content"
%PDF-1.3
%���������
4 0 obj
<< /Length 5 0 R /Filter /FlateDecode >>
stream
...
------WebKitFormBoundaryOJOOGb7N43BxCRlv
The issue is that the request file is a binary file (PDF), and the text gets "mangled". It reports a size of 57234 bytes, when the actual file size (as fetched with a wget
command) is 60248 bytes.
The question is: How to get and send the binary data, without being modified?
I tried replacing response.text()
by response.blob()
, as follows:
response = await fetch("https://wiki.epfl.ch/lapa-studio/documents/DTS/laser%20tutorial.pdf");
response.blob().then(function(content) {
console.log(content.size);
console.log(content);
formData = new FormData();
formData.append("content", content);
fetch("https://wiki.epfl.ch/test.php", {method: 'POST', body: formData});
})
Now I get this log, with the correct file size:
content.size: 60248
content: Blob(60248) {size: 60248, type: "application/pdf"}
However, going to the Developer Network tab, choose the 'test.php' page, navigate to "Requested payload:", it shows that it sends an empty payload:
------WebKitFormBoundaryYoibuD14Ah2cNGAd
Content-Disposition: form-data; name="content"; filename="blob"
Content-Type: application/pdf
------WebKitFormBoundaryYoibuD14Ah2cNGAd--
Note: The webpage I am developing is not at wiki.epfl.ch. I provide this example so that users can try it (and avoid the "Cross-Origin Resource Sharing" problem). My "test.php" page is in php and $_POST['content']
returns the content when using response.text()
, but it returns empty when using response.blob()
. So, even if it is the case that the Developer Network tab "Requested payload:" does not show binary data, this snipped is still not working.
The question is: How to get and send the binary data, without being modified?
Sending binary dataThe send method of the XMLHttpRequest has been extended to enable easy transmission of binary data by accepting an ArrayBuffer , Blob , or File object. The following example creates a text file on-the-fly and uses the POST method to send the "file" to the server.
Convert the blob to an ArrayBuffer (see 2 methods). Create an ArrayBufferView (Int8array in this case), spread it into an array, and then map the view to the binary representation of each number using Number. toString() with a radix of 2 - . toString(2) .
If you want to send a binary file, do not use the .text()
method, as that returns the file decoded using UTF-8, which is not what you want. Instead, use the .blob()
method, which does not attempt to decode the file, and use it directly as the body
parameter of the second fetch()
since it's allowed to be a Blob
:
const response = await fetch("https://wiki.epfl.ch/lapa-studio/documents/DTS/laser%20tutorial.pdf");
const content = await response.blob();
console.log(content.size);
fetch("https://wiki.epfl.ch/test.php", { method: 'POST', body: content });
For parsing this upload format see this answer.
If you want to upload it as part of a multipart/form-data
formatted attachment, you can still use the FormData
API, but doing so isn't necessary to send the binary data to your PHP script. Just for completeness, here's how you'd do that instead:
const response = await fetch("https://wiki.epfl.ch/lapa-studio/documents/DTS/laser%20tutorial.pdf");
const content = await response.blob();
console.log(content.size);
const formData = new FormData();
formData.append("content", content);
fetch("https://wiki.epfl.ch/test.php", { method: 'POST', body: formData });
Try this, by converting blob to DataURL string, you can send binary data without being modified.
response = await fetch("https://wiki.epfl.ch/lapa-studio/documents/DTS/laser%20tutorial.pdf");
response.blob().then(function (content) {
let reader = new FileReader();
reader.addEventListener("loadend", function () {
formData = new FormData();
formData.append("content", reader.result);
fetch("https://wiki.epfl.ch/test.php", { method: 'POST', body: formData });
reader.removeEventListener("loadend");
});
reader.readAsDataURL(content);
});
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