Как отправить двоичные данные (blob) с помощью fetch и FormData?

следующий код работает, как ожидалось. Откройте страницу"https://wiki.epfl.ch/ " в Google Chrome и выполните этот код на консоли разработчика. Примечание: страница"https://wiki.epfl.ch/test.php " не существует, и поэтому он не загружается, но это не проблема.

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});
})

запись:

content.length: 57234
content: %PDF-1.3
%���������
4 0 obj
<< /Length 5 0 R /Filter /FlateDecode >>
stream
x��K��F�����;¢�
...

перейдите на вкладку Сеть разработчика, выберите " тест.страница php, перейдите к " запрошенная полезная нагрузка:", и вы можете увидеть это содержание:

------WebKitFormBoundaryOJOOGb7N43BxCRlv
Content-Disposition: form-data; name="content"

%PDF-1.3
%���������
4 0 obj
<< /Length 5 0 R /Filter /FlateDecode >>
stream
...
------WebKitFormBoundaryOJOOGb7N43BxCRlv

проблема в том, что файл запроса является двоичным файлом (PDF), и текст "искажается". Он сообщает размер 57234 байт, когда фактический размер (так как выбираются с wget command) составляет 60248 байт.

вопрос в том, как получить и отправить двоичные данные без изменения?


я попытался заменить response.text() by response.blob() следующим образом:

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});
})

теперь я получаю этот журнал с правильным файлом размер:

content.size:  60248
content:  Blob(60248) {size: 60248, type: "application/pdf"}

однако, перейдя на вкладку Сеть разработчика, выберите "тест".страница php, перейдите к " запрошенная полезная нагрузка:", она показывает, что она отправляет пустую полезную нагрузку:

------WebKitFormBoundaryYoibuD14Ah2cNGAd
Content-Disposition: form-data; name="content"; filename="blob"
Content-Type: application/pdf


------WebKitFormBoundaryYoibuD14Ah2cNGAd--

Примечание: веб-страница, которую я разрабатываю, не находится в wiki.epfl.ch. Я приведу этот пример, чтобы пользователи могли попробовать его (и избежать проблемы "совместного использования ресурсов"). Мой тест.php " страница находится в php и $_POST['content'] возвращает содержимое при использовании response.text(), но он возвращается пустым, когда используя response.blob(). Таким образом, даже если вкладка "запрошенная полезная нагрузка" в Сети разработчика не отображает двоичные данные, эта обрезка все равно не работает.


вопрос в том, как получить и отправить двоичные данные без изменения?

3 ответов


попробуйте это, Преобразуя blob в строку DataURL, вы можете отправлять двоичные данные без изменения.

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);

 });

если вы хотите отправить двоичный файл, не используйте .text() метод, так как это возвращает файл, декодированный с помощью UTF-8, что не то, что вы хотите. Вместо этого, используйте .blob() метод, который не пытается расшифровать файл, и использовать его непосредственно как


пожалуйста, попробуйте с этим кодом может надеяться, что это поможет вам

 pdfcall(){
var xmlhttp = new XMLHttpRequest(),
method = 'GET',
 xmlhttp.open(method, url, true);
  xmlhttp.responseType = 'blob';
  xmlhttp.onload = (e: any) => {
   console.log(xmlhttp);
if (xmlhttp.status === 200) {
  let blob = new Blob([xmlhttp.response], {type: 'application/pdf'});
  this.pdfSrc = URL.createObjectURL(blob);
  }
};
 xmlhttp.onerror = (e: any) =>{
  console.error(e,'eerr')
    }
  xmlhttp.send();
}