gpt4 book ai didi

javascript - 将 Node 请求或 axios 与流一起使用来下载和解压缩文件未按预期处理背压?

转载 作者:搜寻专家 更新时间:2023-10-31 22:53:16 25 4
gpt4 key购买 nike

我们有一个大约 6 GB 的大文件,它被解压缩到 64 GB 大小(OS 镜像),我们需要使用 http 下载它。我们正在使用 Node 的请求库或 axios。使用以下代码即时下载和解压(管道)文件:

 const downloadUsingHttp = (downloadUrl, destinationPath) => {enter code here
return new Promise((resolve, reject) => {
const unpackedPathWriteStream = fs.createWriteStream(destinationPath);

let totalDownloadSize = 64023257088;
let downloadedSize = 0;
let lastProgressSent = 0;

axios({
method: 'get',
url: downloadUrl,
responseType: 'stream',
auth: {
username: 'user',
password: 'pass'
},
withCredentials: true
}).then(function (response) {
response.data
.on('data', chunk => {
if (totalDownloadSize === 0) {
return;
}
downloadedSize += chunk.length;
const progress = Math.floor((downloadedSize / totalDownloadSize) * 100);

if (progress % 5 !== 0) {
return;
}

if (lastProgressSent === progress) {
return;
}

lastProgressSent = progress;
console.log('Copy progress ', progress + ' %')
})
.pipe(zlib.createUnzip())
.pipe(unpackedPathWriteStream)

}).catch((err) => {
console.log(err.message)
});

unpackedPathWriteStream
.on('error', err => {
console.log(err);
reject(err);
}).on('end', () => {
resolve();
})
})
};

downloadUsingHttp(
'https://example.com/storage/file.raw.gz',
'/data/downloaded-and-unziped.raw'
);

我们运行此代码的机器有 2 GB 的 RAM。运行这段代码时,出现的问题是机器内存不足,进度大约为 15%, Node 应用程序崩溃。有时甚至整台机器都没有反应,需要重启。

所以看起来像back pressure handling在这种情况下,在流上实现的 .pipe() 槽不起作用。例如,当不通过 h​​ttp(使用请求或 axios 库)下载文件时,而是使用可读和可写流进行下载时,使用管道方法进行复制和解压缩的相同操作是有效的,并且没有内存耗尽。

另外需要说明的是,这个问题只有在本地网络(本地开发环境)中进行http下载时才会出现。

如有任何帮助,我们将不胜感激。

更新

我们已经尝试将流的速度限制为 100 KB/s,并且它似乎在没有增加 RAM 内存使用量的情况下起作用。当更改为 1 MB/s 时,使用量会增加,最终会停止应用程序。我们使用 stream-throttle 库来尝试这个。

最佳答案

我对管道没有太多经验,但是如何分块加载文件并将它们一次一个地送入管道呢?然后加载下一个 block 。因此管道一次只需要处理几 MB 的数据。

我想象的是这样的:

const downloadUsingHttp = (downloadUrl, destinationPath, chunkSize = 10<<20) => {
const writeStream = fs.createWriteStream(destinationPath);
const unzip = zlib.createUnzip();

const auth = {
username: 'user',
password: 'pass'
};

const nextChunk = () => axios({
method: 'get',
url: downloadUrl,
responseType: 'stream',
auth: auth,
withCredentials: true,
headers: {
Range: `bytes=${offset}-${(offset += chunkSize)}`
}
}).then(downThePipe);

const downThePipe = response => {
console.log("progress %i%% ( %i / %i bytes )", offset / length * 100, offset, length);
response.data.pipe(unzip).pipe(writeStream);

return offset < length ? nextChunk() : null;
};

let offset = 0, length;
return axios({
method: "HEAD",
url: downloadUrl,
auth: auth,
withCredentials: true,
}).then(response => {
length = response.headers["Content-Length"];
return nextChunk();
});
};



downloadUsingHttp(
'https://example.com/storage/file.raw.gz',
'/data/downloaded-and-unziped.raw'
);

也许,如果下载仍然太快,您可能希望延迟加载 nextChunk() 直到 pipe() 工作完成。但同样,我使用这些管道已经有一段时间了。

关于javascript - 将 Node 请求或 axios 与流一起使用来下载和解压缩文件未按预期处理背压?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58101164/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com