我想使用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!');
});
});
文件已保存,但内容已损坏...
如何正确保存文件?
答案 0 :(得分:38)
实际上,我认为以前接受的答案存在一些缺陷,因为它不能正确处理写流,因此,如果在Axios给您响应后调用“ then()”,您最终将拥有部分下载的文件
当下载稍大的文件时,这是一个更合适的解决方案:
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()
,并确保下载的文件已完成处理。
答案 1 :(得分:2)
您可以简单地使用response.data.pipe
和fs.createWriteStream
将响应发送到文件中
axios({
method: "get",
url: "https://xxx/my.pdf",
responseType: "stream"
}).then(function (response) {
response.data.pipe(fs.createWriteStream("/temp/my.pdf"));
});
答案 2 :(得分:2)
// This works perfectly well!
const axios = require('axios');
axios.get('http://www.sclance.com/pngs/png-file-download/png_file_download_1057991.png', {responseType: "stream"} )
.then(response => {
// Saving file to working directory
response.data.pipe(fs.createWriteStream("todays_picture.png"));
})
.catch(error => {
console.log(error);
});
答案 3 :(得分:1)
if
对我来说很好
答案 4 :(得分:1)
文件损坏的问题是由于 节点流中的反压 。您可能会发现此链接对于阅读以下内容很有帮助:https://nodejs.org/es/docs/guides/backpressuring-in-streams/
我不是真的喜欢在JS代码中使用Promise基本声明性对象,因为我认为这会污染实际的核心逻辑并使代码难以阅读。最重要的是,您必须提供事件处理程序和侦听器以确保代码完成。
下面给出了与被接受的答案所建议的相同逻辑的更简洁的方法。它使用 流管道 的概念。
npm uninstall nyc
npm i --save-dev nyc
我希望您觉得这有用。
答案 5 :(得分:0)
这是我在节点js上运行的示例代码 出现同步错误
应为 writeFile 而不是 WriteFile
const axios = require('axios');
const fs = require('fs');
axios.get('http://www.africau.edu/images/default/sample.pdf', {responseType: 'blob'}).then(response => {
fs.writeFile('./my.pdf', response.data, (err) => {
if (err) throw err;
console.log('The file has been saved!');
});
});
文件保存后,在文本编辑器中看起来像,但是文件已正确保存
%PDF-1.3
%����
1 0 obj
<<
/Type /Catalog
/Outlines 2 0 R
/Pages 3 0 R
>>
endobj
2 0 obj
<<
/Type /Outlines
/Count 0
>>
endobj
3 0 obj
<<
/Type /Pages
/Count 2
/Kids [ 4 0 R 6 0 R ]
>>
endobj
答案 6 :(得分:0)
node fileSystem writeFile
默认将数据编码为UTF8。在您的情况下可能是个问题。
尝试将编码设置为null
,然后跳过对接收到的数据进行编码的操作:
fs.writeFile('/temp/my.pdf', response.data, {encoding: 'null'}, (err) => {...}
如果仅声明编码而没有其他选项,则还可以将编码作为字符串(而不是options对象)进行十进制化。字符串将作为编码值处理。这样:
fs.writeFile('/temp/my.pdf', response.data, 'null', (err) => {...}
更多信息,请参见fileSystem API write_file
答案 7 :(得分:0)
我已经尝试过,并且确信使用response.data.pipe
和fs.createWriteStream
可以正常工作。
此外,我想添加我的情况和解决方案
情况:
koa
开发node.js服务器axios
通过网址获取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),
}
})
在此解决方案中,不需要写入文件和读取文件,效率更高。