使用 nodejs 下载多个文件不一致,但不使用 php
Inconsistency downloading multiple files with nodejs but not with php
我在 nodejs 和 php 上编写了一个脚本,它实现了同样的事情,ping API,检索文件列表,遍历每个文件并将它们下载到磁盘到指定的位置位置。
左边是nodejs,右边是php。
我观察到,某些文件在 nodejs 中每次尝试时随机下载失败。在某种尝试中,所有文件也会成功。在 php 上,每次尝试都是一致的,所有文件都可以正常下载。
nodejs 中是否缺少某些内容,即默认情况下未通过下载文件请求包含的 configuration/header?或者下载多个文件是否需要在 nodejs 中进行不同的处理?
Nodejs 代码:
const http = require('https');
const fs = require('fs');
function getResponse(url, callback) {
http.get(url, response => {
let body = '';
response.on('data', data => {
body += data
})
response.on('end', () => {
callback(JSON.parse(body))
})
})
}
var download = function (url, dest, callback) {
http.get(url, response => {
response.on('error', function (err) {
console.log(err)
})
.pipe(fs.createWriteStream(dest))
.on('close', callback)
});
};
getResponse('https://wallhaven.cc/api/v1/search?page=1', json => {
json.data.forEach((item, index) => {
download(item.path, `files/file-${index}.jpg`, function () {
console.log('Finished Downloading' + `file-${index}.jpg`)
});
})
})
PHP代码
$client = new \GuzzleHttp\Client();
$response = $client->get('https://wallhaven.cc/api/v1/search?page=1');
$json = json_decode((string)$response->getBody());
$rows = $json->data;
foreach ($rows as $index => $row) {
$content = file_get_contents($row->path);
Storage::put("files/file-$index.jpg", $content);
}
return 'done';
没有魔法 header 可以让它在 Node.js 中发挥作用。如果有时它有效,而其他时候请求花费的时间太长,服务器可能会由于 rate-limiting.
而静静地丢弃请求
我可以看出 PHP 是同步的,将每个文件一个一个地下载到内存中,然后放入一个文件中,而在 Node.js 中,您会立即触发每个请求并同时处理它们,将内容流式传输到文件中。接收乱序的数据包是正常的,TCP 协议可以确保它们重新组合在一起。 Node.js 能够做到这样的事情,您很可能遇到了服务器的安全功能或其他限制。
如果时间不是问题,我建议修改 Node.js 减慢请求速度,方法是限制并发请求的数量或一个一个地执行(最简单的选择,请参阅 async/await
,promises,axios 库)。跟进你的 Reddit post,学习 C++ 来完成这项任务很可能不会产生任何好处。事实上,这要困难几个数量级。 Node.js 是一个非常强大的平台,不仅可以下载文件。
在不知道问题的真正原因的情况下,除了尝试分析您的请求并了解它们出了什么问题之外,我无法提供更多建议。
我在 nodejs 和 php 上编写了一个脚本,它实现了同样的事情,ping API,检索文件列表,遍历每个文件并将它们下载到磁盘到指定的位置位置。
左边是nodejs,右边是php。
我观察到,某些文件在 nodejs 中每次尝试时随机下载失败。在某种尝试中,所有文件也会成功。在 php 上,每次尝试都是一致的,所有文件都可以正常下载。
nodejs 中是否缺少某些内容,即默认情况下未通过下载文件请求包含的 configuration/header?或者下载多个文件是否需要在 nodejs 中进行不同的处理?
Nodejs 代码:
const http = require('https');
const fs = require('fs');
function getResponse(url, callback) {
http.get(url, response => {
let body = '';
response.on('data', data => {
body += data
})
response.on('end', () => {
callback(JSON.parse(body))
})
})
}
var download = function (url, dest, callback) {
http.get(url, response => {
response.on('error', function (err) {
console.log(err)
})
.pipe(fs.createWriteStream(dest))
.on('close', callback)
});
};
getResponse('https://wallhaven.cc/api/v1/search?page=1', json => {
json.data.forEach((item, index) => {
download(item.path, `files/file-${index}.jpg`, function () {
console.log('Finished Downloading' + `file-${index}.jpg`)
});
})
})
PHP代码
$client = new \GuzzleHttp\Client();
$response = $client->get('https://wallhaven.cc/api/v1/search?page=1');
$json = json_decode((string)$response->getBody());
$rows = $json->data;
foreach ($rows as $index => $row) {
$content = file_get_contents($row->path);
Storage::put("files/file-$index.jpg", $content);
}
return 'done';
没有魔法 header 可以让它在 Node.js 中发挥作用。如果有时它有效,而其他时候请求花费的时间太长,服务器可能会由于 rate-limiting.
而静静地丢弃请求我可以看出 PHP 是同步的,将每个文件一个一个地下载到内存中,然后放入一个文件中,而在 Node.js 中,您会立即触发每个请求并同时处理它们,将内容流式传输到文件中。接收乱序的数据包是正常的,TCP 协议可以确保它们重新组合在一起。 Node.js 能够做到这样的事情,您很可能遇到了服务器的安全功能或其他限制。
如果时间不是问题,我建议修改 Node.js 减慢请求速度,方法是限制并发请求的数量或一个一个地执行(最简单的选择,请参阅 async/await
,promises,axios 库)。跟进你的 Reddit post,学习 C++ 来完成这项任务很可能不会产生任何好处。事实上,这要困难几个数量级。 Node.js 是一个非常强大的平台,不仅可以下载文件。
在不知道问题的真正原因的情况下,除了尝试分析您的请求并了解它们出了什么问题之外,我无法提供更多建议。