ar0*_*968 1 javascript node.js axios
我想使用下载pdf文件,axios并使用将其保存在磁盘(服务器端)上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!');
});
});
Run Code Online (Sandbox Code Playgroud)
文件已保存,但内容已损坏...
如何正确保存文件?
cso*_*iou 66
实际上,我认为之前接受的答案存在一些缺陷,因为它无法正确处理写入流,因此如果在 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;
});
});
});
}
Run Code Online (Sandbox Code Playgroud)
这样,您可以调用downloadFile(),调用then()返回的承诺,并确保下载的文件已完成处理。
或者,如果你使用更现代的 NodeJS 版本,你可以试试这个:
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
});
}
Run Code Online (Sandbox Code Playgroud)
use*_*378 34
文件损坏的问题是由于节点流中的背压造成的。您可能会发现此链接对阅读很有用:https ://nodejs.org/es/docs/guides/backpressuring-in-streams/
我不太喜欢在 JS 代码中使用 Promise 基声明对象,因为我觉得它污染了实际的核心逻辑并使代码难以阅读。最重要的是,您必须配置事件处理程序和侦听器以确保代码完成。
下面给出了与接受的答案提出的相同逻辑的更清晰的方法。它使用流管道的概念。
const util = require('util');
const stream = require('stream');
const pipeline = util.promisify(stream.pipeline);
const downloadFile = async () => {
try {
const request = await axios.get('https://xxx/my.pdf', {
responseType: 'stream',
});
await pipeline(request.data, fs.createWriteStream('/temp/my.pdf'));
console.log('download pdf pipeline successful');
} catch (error) {
console.error('download pdf pipeline failed', error);
}
}
exports.downloadFile = downloadFile
Run Code Online (Sandbox Code Playgroud)
希望这个对你有帮助。
小智 14
const res = await axios.get(url, { responseType: 'arraybuffer' });
fs.writeFileSync(downloadDestination, res.data);
Run Code Online (Sandbox Code Playgroud)
pon*_*tek 13
您可以简单地使用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"));
});
Run Code Online (Sandbox Code Playgroud)
// 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);
});
Run Code Online (Sandbox Code Playgroud)
节点文件系统writeFile默认将数据编码为 UTF8。这对你来说可能是个问题。
尝试将编码设置为null并跳过对接收到的数据进行编码:
fs.writeFile('/temp/my.pdf', response.data, {encoding: null}, (err) => {...}
Run Code Online (Sandbox Code Playgroud)
如果您只声明编码而没有其他选项,您还可以将编码标记为字符串(而不是选项对象)。字符串将作为编码值处理。像这样:
fs.writeFile('/temp/my.pdf', response.data, 'null', (err) => {...}
Run Code Online (Sandbox Code Playgroud)
更多内容请阅读fileSystem API write_file
有一种更简单的方法,只需几行即可完成:
import fs from 'fs';
const fsPromises = fs.promises;
const fileResponse = await axios({
url: fileUrl,
method: "GET",
responseType: "stream",
});
// Write file to disk (here I use fs.promise but you can use writeFileSync it's equal
await fsPromises.writeFile(filePath, fileResponse.data);
Run Code Online (Sandbox Code Playgroud)
Axios具有内部处理能力streams,您不必为此干预低级 Node API。
查看https://axios-http.com/docs/req_config(responseType在文档中查找您可以使用的所有类型的部分)。
| 归档时间: |
|
| 查看次数: |
5269 次 |
| 最近记录: |