web-dev-qa-db-fra.com

Comment télécharger des fichiers avec axios

J'utilise axios pour les requêtes HTTP de base telles que get et post, et cela fonctionne bien. Maintenant, je dois aussi pouvoir télécharger des fichiers Excel. Est-ce possible avec axios. Si tel est le cas, quelqu’un at-il un exemple de code? Sinon, que puis-je utiliser dans une application de réaction pour faire la même chose?

19
David Choi

Lorsque la réponse est fournie avec un fichier téléchargeable, les en-têtes de réponse ressemblent à

Content-Disposition: "attachment;filename=report.xls"
Content-Type: "application/octet-stream" // or Content-type: "application/vnd.ms-Excel"

Ce que vous pouvez faire est de créer un composant séparé, qui contiendra un iframe caché. 

  import * as React from 'react';

  var MyIframe = React.createClass({

     render: function() {
         return (
           <div style={{display: 'none'}}>
               <iframe src={this.props.iframeSrc} />
           </div>
         );
     }
  });

Maintenant, vous pouvez transmettre l'URL du fichier téléchargeable comme accessoire de ce composant. Ainsi, lorsque ce composant recevra un accessoire, il sera rendu et le fichier sera téléchargé. 

Edit: Vous pouvez également utiliser js-file-download module. Lien vers le repo Github

const FileDownload = require('js-file-download');

Axios.get(`http://localhost/downloadFile`)
   .then((response) => {
        FileDownload(response.data, 'report.csv');
   });

J'espère que cela t'aides :)

35
Hardik Modha

Téléchargement de fichiers (avec Axios et Security)

En réalité, cela est encore plus complexe lorsque vous souhaitez télécharger des fichiers à l'aide d'Axios et de certains moyens de sécurité. Pour éviter que quiconque ne consacre trop de temps à résoudre ce problème, laissez-moi vous guider.

Vous devez faire 3 choses:

1. Configure your server to permit the browser to see required HTTP headers
2. Implement the server-side service, and making it advertise the correct file type for the downloaded file.
3. Implementing an Axios handler to trigger a FileDownload dialog within the browser

Ces étapes sont généralement réalisables - mais sont considérablement compliquées par la relation du navigateur avec CORS. Un pas après l'autre:

1. Configurez votre serveur (HTTP)

Lors de l'utilisation de la sécurité de transport, l'exécution de JavaScript dans un navigateur ne [par conception] peut accéder qu'à 6 en-têtes HTTP réellement envoyés par le serveur HTTP. Si nous souhaitons que le serveur suggère un nom de fichier pour le téléchargement, nous devons informer le navigateur qu'il est "correct" de permettre à JavaScript d'accéder à d'autres en-têtes où le nom de fichier suggéré serait transporté.

Supposons, dans l’intérêt de la discussion, que nous souhaitons que le serveur transmette le nom de fichier suggéré dans un en-tête HTTP appelé X-Suggested-Filename. Le serveur HTTP indique au navigateur qu'il est OK exposer l'en-tête personnalisé reçu à JavaScript/Axios avec l'en-tête suivant:

Access-Control-Expose-Headers: X-Suggested-Filename

La manière exacte de configurer votre serveur HTTP pour définir cet en-tête varie d'un produit à l'autre. 

Voir https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers pour une explication complète et une description détaillée de ces en-têtes standard. 

2. Implémenter le service côté serveur

L'implémentation de votre service côté serveur doit maintenant effectuer 2 choses:

1. Create the (binary) document and assign correct ContentType to the response
2. Assign the custom header (X-Suggested-Filename) containing the suggested file name for the client

Cela se fait de différentes manières en fonction de la pile de technologies choisie. Je vais esquisser un exemple en utilisant le standard JavaEE 7 qui devrait générer un rapport Excel:

@GET
@Path("/report/Excel")
@Produces("application/vnd.ms-Excel")
public Response getAllergyAndPreferencesReport() {

    // Create the document which should be downloaded
    final byte[] theDocumentData = .... 

    // Define a suggested filename
    final String filename = ... 

    // Create the JAXRS response
    // Don't forget to include the filename in 2 HTTP headers: 
    //
    // a) The standard 'Content-Disposition' one, and
    // b) The custom 'X-Suggested-Filename'  
    //
    final Response.ResponseBuilder builder = Response.ok(
            theDocumentData, "application/vnd.ms-Excel")
            .header("X-Suggested-Filename", fileName);
    builder.header("Content-Disposition", "attachment; filename=" + fileName);

    // All Done.
    return builder.build();
}

Le service émet maintenant le document binaire (un rapport Excel, dans ce cas), définit le type de contenu correct et envoie également un en-tête HTTP personnalisé contenant le nom de fichier suggéré à utiliser lors de l'enregistrement du document.

3. Implémenter un gestionnaire Axios pour le document reçu

Il y a quelques pièges ici, alors assurons-nous que tous les détails sont correctement configurés:

  1. Le service répond à @GET (HTTP GET). L’appel axios doit donc être 'axios.get (...)'.
  2. Le document étant transmis sous forme de flux d'octets, vous devez indiquer à axios de traiter la réponse comme un blob HTML5. (I. _ {responseType: 'blob'} _).
  3. Dans ce cas, la bibliothèque JavaScript de l’économiseur de fichiers est utilisée pour ouvrir la boîte de dialogue du navigateur. Cependant, vous pouvez en choisir un autre. 

La mise en œuvre squelette d’Axios ressemblerait alors à:

 // Fetch the dynamically generated Excel document from the server.
 axios.get(resource, {responseType: 'blob'}).then((response) => {

    // Log somewhat to show that the browser actually exposes the custom HTTP header
    const fileNameHeader = "x-suggested-filename";
    const suggestedFileName = response.headers[fileNameHeader];'
    const effectiveFileName = (suggestedFileName === undefined
                ? "allergierOchPreferenser.xls"
                : suggestedFileName);
    console.log("Received header [" + fileNameHeader + "]: " + suggestedFileName
                + ", effective fileName: " + effectiveFileName);

    // Let the user save the file.
    FileSaver.saveAs(response.data, effectiveFileName);

    }).catch((response) => {
        console.error("Could not Download the Excel report from the backend.", response);
    });
26
Lennart Jörelid

Une solution plus générale

axios({
  url: 'http://api.dev/file-download', //your url
  method: 'GET',
  responseType: 'blob', // important
}).then((response) => {
   const url = window.URL.createObjectURL(new Blob([response.data]));
   const link = document.createElement('a');
   link.href = url;
   link.setAttribute('download', 'file.pdf'); //or any other extension
   document.body.appendChild(link);
   link.click();
});

Découvrez les défauts sur https://Gist.github.com/javilobo8/097c30a233786be52070986d8cdb1743

Crédits complets à: https://Gist.github.com/javilobo8

8
Viney
        axios.get(
            '/app/export'
        ).then(response => {    
            const url = window.URL.createObjectURL(new Blob([response]));
            const link = document.createElement('a');
            link.href = url;
            const fileName = `${+ new Date()}.csv`// whatever your file name .
            link.setAttribute('download', fileName);
            document.body.appendChild(link);
            link.click();
            link.remove();// you need to remove that elelment which is created before.
})
0
Nitin Tyagi

L'astuce consiste à créer une balise d'ancrage invisible dans la render() et à ajouter une React ref permettant de déclencher un clic une fois la réponse obtenue:

class Example extends Component {
    state = {
        ref: React.createRef()
    }

    exportCSV = () => {
        axios.get(
            '/app/export'
        ).then(response => {
            let blob = new Blob([response.data], {type: 'application/octet-stream'})
            let ref = this.state.ref
            ref.current.href = URL.createObjectURL(blob)
            ref.current.download = 'data.csv'
            ref.current.click()
        })
    }

    render(){
        return(
            <div>
                <a style={{display: 'none'}} href='empty' ref={this.state.ref}>ref</a>
                <button onClick={this.exportCSV}>Export CSV</button>
            </div>
        )
    }
}

Voici la documentation: https://reactjs.org/docs/refs-and-the-dom.html . Vous pouvez trouver une idée similaire ici: https://thewebtier.com/snippets/download-files-with-axios/ .

0
enjolrasyn