使用 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 是一个非常强大的平台,不仅可以下载文件。

在不知道问题的真正原因的情况下,除了尝试分析您的请求并了解它们出了什么问题之外,我无法提供更多建议。