web-dev-qa-db-fra.com

node.js axios télécharger le fichier et writeFile

je veux télécharger un fichier pdf avec axios et enregistrer sur le disque (côté serveur) avec fs.writeFile, j'ai essayé:

axios.get('https://xxx/my.pdf', {responseType: 'blob'}).then(response => {
    fs.writeFile('/temp/my.pdf', response.data, (err) => {
        if (err) throw err;
        console.log('The file has been saved!');
    });
});

le fichier est enregistré mais le contenu est cassé ...

comment enregistrer correctement le fichier?

6
ar099968

J'ai essayé et je suis sûr que l'utilisation de response.data.pipe et fs.createWriteStream peut marcher.


De plus, je veux ajouter ma situation et ma solution

Situation:

  • en utilisant koa pour développer un serveur node.js
  • en utilisant axios pour obtenir un pdf via url
  • en utilisant pdf-parse pour analyser le pdf
  • extraire des informations du pdf et les renvoyer sous json au navigateur

Solution:

const Koa = require('koa');
const app = new Koa();
const axios = require('axios')
const fs = require("fs")
const pdf = require('pdf-parse');
const utils = require('./utils')

app.listen(process.env.PORT || 3000)

app.use(async (ctx, next) => {
      let url = 'https://path/name.pdf'
      let resp = await axios({
          url: encodeURI(url),
          responseType: 'arraybuffer'
        })

        let data = await pdf(resp.data)

        ctx.body = {
            phone: utils.getPhone(data.text),
            email: utils.getEmail(data.text),
        }
})

Dans cette solution, il n'a pas besoin d'écrire et de lire un fichier, c'est plus efficace.

0
levy9527

En fait, je pense que la réponse acceptée a quelques défauts, car elle ne traitera pas correctement le flux écrit, donc si vous appelez "then ()" après qu'Axios vous ait donné la réponse, vous finirez par avoir un fichier partiellement téléchargé.

Il s'agit d'une solution plus appropriée lors du téléchargement de fichiers légèrement plus volumineux:

export async function downloadFile(fileUrl: string, outputLocationPath: string) {
  const writer = createWriteStream(outputLocationPath);

  return Axios({
    method: 'get',
    url: fileUrl,
    responseType: 'stream',
  }).then(response => {

    //ensure that the user can call `then()` only when the file has
    //been downloaded entirely.

    return new Promise((resolve, reject) => {
      response.data.pipe(writer);
      let error = null;
      writer.on('error', err => {
        error = err;
        writer.close();
        reject(err);
      });
      writer.on('close', () => {
        if (!error) {
          resolve(true);
        }
        //no need to call the reject here, as it will have been called in the
        //'error' stream;
      });
    });
  });
}

De cette façon, vous pouvez appeler downloadFile(), appeler then() sur la promesse retournée et vous assurer que le fichier téléchargé aura terminé le traitement.

0
csotiriou