node.js axios下载文件流并写入File [英] node.js axios download file stream and writeFile
问题描述
我想使用 axios
下载pdf文件,并使用 fs.writeFile
保存在磁盘(服务器端)上,我已经尝试过:
i want download a pdf file with axios
and save on disk (server side) with fs.writeFile
, i have tried:
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!');
});
});
文件已保存,但内容已损坏...
the file is saved but the content is broken...
如何正确保存文件?
推荐答案
实际上,我相信先前接受的答案存在一些缺陷,因为它不能正确处理写流,因此如果您调用"then()",在Axios给您答复后,您最终将拥有部分下载的文件.
Actually, I believe the previously accepted answer has some flaws, as it will not handle the writestream properly, so if you call "then()" after Axios has given you the response, you will end up having a partially downloaded file.
当下载稍大的文件时,这是一个更合适的解决方案:
This is a more appropriate solution when downloading slightly larger files:
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;
});
});
});
}
通过这种方式,您可以调用 downloadFile()
,对返回的承诺调用 then()
,并确保已下载的文件已完成处理.
This way, you can call downloadFile()
, call then()
on the returned promise, and making sure that the downloaded file will have completed processing.
或者,如果您使用更新版本的NodeJS,则可以尝试以下方法:
Or, if you use a more modern version of NodeJS, you can try this instead:
import * as stream from 'stream';
import { promisify } from 'util';
const finished = promisify(stream.finished);
export async function downloadFile(fileUrl: string, outputLocationPath: string): Promise<any> {
const writer = createWriteStream(outputLocationPath);
return Axios({
method: 'get',
url: fileUrl,
responseType: 'stream',
}).then(async response => {
response.data.pipe(writer);
return finished(writer); //this is a Promise
});
}
这篇关于node.js axios下载文件流并写入File的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!