web-dev-qa-db-ja.com

node.js axiosダウンロードファイルとwriteFile

axiosを使用してpdfファイルをダウンロードし、fs.writeFileを使用してディスク(サーバー側)に保存したいのですが、試しました。

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

ファイルは保存されますが、内容が壊れています...

ファイルを正しく保存するにはどうすればよいですか?

6
ar099968

私は試しましたが、response.data.pipefs.createWriteStreamを使用してもうまくいくと確信しています。


その上、自分の状況と解決策を追加したい

状況:

  • koaを使用してnode.jsサーバーを開発する
  • axiosを使用してURL経由でPDFを取得する
  • pdf-parseを使用してPDFを解析する
  • pDFのいくつかの情報を抽出し、jsonとしてブラウザに返します

解決:

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

このソリューションでは、ファイルの書き込みとファイルの読み取りを行う必要がなく、より効率的です。

0
levy9527

実際には、受け入れられた回答には書き込みストリームが適切に処理されないため、受け入れられた回答にはいくつかの欠陥があると考えています。

少し大きいファイルをダウンロードする場合、これはより適切なソリューションです。

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

このようにして、返されたpromiseでdownloadFile()を呼び出し、then()を呼び出して、ダウンロードしたファイルの処理が完了したことを確認できます。

0
csotiriou