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!');
});
});
ファイルは保存されますが、内容が壊れています...
ファイルを正しく保存するにはどうすればよいですか?
私は試しましたが、response.data.pipe
とfs.createWriteStream
を使用してもうまくいくと確信しています。
その上、自分の状況と解決策を追加したい
状況:
koa
を使用してnode.jsサーバーを開発するaxios
を使用してURL経由でPDFを取得するpdf-parse
を使用してPDFを解析する解決:
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),
}
})
このソリューションでは、ファイルの書き込みとファイルの読み取りを行う必要がなく、より効率的です。
実際には、受け入れられた回答には書き込みストリームが適切に処理されないため、受け入れられた回答にはいくつかの欠陥があると考えています。
少し大きいファイルをダウンロードする場合、これはより適切なソリューションです。
_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()
を呼び出して、ダウンロードしたファイルの処理が完了したことを確認できます。