web-dev-qa-db-fra.com

Comment puis-je envoyer des données binaires (blob) en utilisant fetch et FormData?

Le code suivant fonctionne comme prévu. Ouvrez la page " https://wiki.epfl.ch/ " sur Google Chrome et exécutez ce code dans la console du développeur. Remarque: la page " https://wiki.epfl.ch/test.php " n’existe pas et ne se charge pas, mais ce n’est pas le problème.

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

Il enregistre:

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

Allez sur l'onglet Réseau de développeurs, choisissez la page 'test.php', naviguez jusqu'à "Charge utile demandée:" et vous pourrez voir ce contenu:

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

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

Le problème est que le fichier de demande est un fichier binaire (PDF) et que le texte est "mutilé". Il signale une taille de 57234 octets, lorsque la taille réelle du fichier (telle qu'elle est extraite avec une commande wget) est de 60248 octets.

La question est: Comment obtenir et envoyer les données binaires sans être modifiées?


J'ai essayé de remplacer response.text() par response.blob(), comme suit:

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

Maintenant, je reçois ce journal, avec la taille de fichier correcte:

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

Cependant, dans l’onglet Réseau de développeurs, choisissez la page 'test.php', accédez à "Charge utile demandée:", elle indique qu’elle envoie une charge utile vide:

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


------WebKitFormBoundaryYoibuD14Ah2cNGAd--

Remarque: la page Web que je développe ne se trouve pas sur wiki.epfl.ch. Je fournis cet exemple pour que les utilisateurs puissent l'essayer (et éviter le problème du "partage de ressources d'origine croisée"). Ma page "test.php" est en php et $_POST['content'] renvoie le contenu lorsque vous utilisez response.text(), mais elle renvoie vide lorsque vous utilisez response.blob(). Ainsi, même s’il est vrai que l’onglet Réseau demandé "Données utiles demandées:" n’affiche pas de données binaires, cette capture ne fonctionne toujours pas.


La question est: Comment obtenir et envoyer les données binaires sans être modifiées?

6
David Portabella

Essayez ceci, en convertissant blob en chaîne DataURL, vous pouvez envoyer des données binaires sans être modifié.

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

 });
1
Waseem Ahmed

Si vous souhaitez envoyer un fichier binaire, n'utilisez pas la méthode .text() , car cela renvoie le fichier décodé à l'aide de UTF-8, ce qui n'est pas ce que vous voulez. À la place, utilisez la méthode .blob() , qui ne tente pas de décoder le fichier, et utilisez-le directement comme paramètre body du deuxième fetch() car il est autorisé à être 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});

Pour analyser ce format de téléchargement, voir cette réponse .

Si vous souhaitez le télécharger dans le cadre d'une pièce jointe au format multipart/form-data, vous pouvez toujours utiliser l'API FormData, mais il n'est pas nécessaire d'envoyer les données binaires à votre script PHP.

1
Patrick Roberts

S'il vous plaît essayez avec ce code peut espérer qu'il va vous aider

 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();
}
0
Manoj Bhardwaj