2
votes

Essayer d'envoyer un zip du backend au frontend

À un moment donné dans mon application Web ember.js , l'utilisateur a la possibilité de télécharger un fichier zip. En cliquant sur le bouton, une action est déclenchée qui envoie une requête au serveur backend, qui génère le zip et le renvoie. Idéalement, le zip devrait alors être téléchargé automatiquement.

Dans mon backend endpoint je retourne avec

HTTP/1.1 200 OK
X-Powered-By: Undertow/1
Cache-Control: no-store
Date: Tue, 19 Feb 2019 16:34:35 GMT
Server: WildFly/10
Content-Type: application/zip
Content-Disposition: attachment; filename="filename.zip"
Connection: close
Transfer-Encoding: chunked

Dans le frontend que j'ai (adapté de ici )

submit() {
  var formData = new FormData(this);
  let token = this.get('session.data.authenticated.token');
  jquery.ajax({
    url: `myUrl`,
    data: formData,
    processData: false,
    contentType: false,
    beforeSend: function(xhr) {xhr.setRequestHeader('Authorization', `Bearer ${token}`)},
    type: 'POST',
    success: function(data) {
      var blob = new Blob([data], {type: 'application/zip'});
      let a = document.createElement("a");
      a.style = "display: none";
      document.body.appendChild(a);
      let url = window.URL.createObjectURL(blob);
      a.href = url;
      a.download = 'myFile.zip';
      a.click();
      window.URL.revokeObjectURL(url);
    },
    failure: function() {
      // other stuff
    }
  })
}

Les en-têtes de réponse sont les suivant:

return Response
        .ok(FileUtils.readFileToByteArray(new File(tmpZipFilename))) // tmpZipFilename is a String
        .type("application/zip")
        .header("Content-Disposition", "attachment; filename=\"" + finalZipFilename + "\"")
        .build();

J'ai confirmé que tmpZipFilename dans la section backend pointe correctement vers un fichier zip approprié. Et lorsque l'utilisateur clique sur le bouton de téléchargement, un fichier appelé myFile.zip est effectivement téléchargé. Cependant, le fichier téléchargé n'est pas décompressable et sa taille est différente de celle du fichier correct pointé par tmpZipFilename . Qu'est-ce que je fais mal?


4 commentaires

Vous ne concaténez pas correctement ces chaînes pour une seule. "pièce jointe; filename = \" "+ finalZipFilename +" \ ""


Pourriez-vous jeter un œil dans le fichier zip avec un éditeur de texte? C'est peut-être un fichier html avec une erreur du serveur.


Ressemble à des données binaires avec beaucoup de s


J'ai couru un diff sur la vue de l'éditeur de texte des bons et des mauvais zips. Ils sont presque identiques, sauf que chaque ligne du mauvais zip manque quelques s aléatoires


3 Réponses :


1
votes

La réponse était simplement d'ajouter dataType: 'arraybuffer' :

...
jquery.ajax({
    url: 'myUrl',
    data: formData,
    processData: false,
    contentType: false,
    dataType: 'arraybuffer',
    beforeSend: function(xhr) {
...


0 commentaires

0
votes

En fait, pour télécharger des fichiers, la meilleure solution consiste simplement à appeler window.open .


0 commentaires

0
votes

SI votre API renvoie un fichier réel et que le type de contenu et la disposition sont correctement définis, vous pouvez simplement créer un lien naturel dans l'interface vers le point de terminaison de l'API, ou utiliser un formulaire standard et non une requête AJAX, comme le téléchargement du fichier se déclenchera et vous resterez au même endroit en ce qui concerne la veuve.

Pour la première option:

<form action="<API ENDPOINT>" method="post">
  <!-- Standard input types named appropriately
</form>

Cela peut fonctionner en liant les paramètres à la chaîne d'URL. Cependant, je déconseillerais cette méthode, sauf si vous avez un moyen de créer des JETONS D'AUTHENTIFICATION SIGNÉS UTILISATION UNIQUE ET OBTENIR , car vous ne devriez jamais envoyer de jetons d'accès à un endroit lisible.

L'option 2 consiste à créer un formulaire HTML générique où l'action est le point de terminaison de l'API, où vous pouvez transmettre le jeton dans les données de publication. Si votre point de terminaison API retourne simplement un fichier approprié, lorsque le formulaire est soumis, le fichier doit être téléchargé et vous devriez pouvoir rester sur la même page.

<a href="<API_ENDPOINT>?token=<token>&param1=something&param2=something">download</a>

Ce ne sont que quelques solutions. Personnellement, j'aime l'option 1, mais seulement si vous pouvez la faire fonctionner en toute sécurité. Recherchez des méthodes d'authentification HMAC pour créer ce jeton à usage unique si vous pouvez stocker et gérer un nonce d'un type quelconque sur le back-end. Fonctionne bien avec les JWT.


0 commentaires