【问题标题】:NodeJS: Download 10'000+ Images From ServerNodeJS:从服务器下载 10'000 多张图片
【发布时间】:2019-11-22 00:17:20
【问题描述】:

我需要从服务器下载 10'000 多张图片。为此,我编写了这个小脚本。

const http = require('http')
const fs = require('fs')

const opt = {
  agent: new http.Agent({
    keepAlive: true,
    maxSockets: 5
  }),
  headers: {
    'user-agent': 'foo'
  }
}

for (let i = 0; i < 10000; i++) {
  http.get(`http://www.example.com/${i}.png`, opt, (res) => {
    console.log(i)
    if (res.statusCode !== 200) return
    res.pipe(fs.createWriteStream(`resource/${i}.png`))
  })
}

问题在于,过了一会儿我得到Error: read ECONNRESETError: socket hang up

我已经设置了keepAlive: truemaxSockets: 5

我唯一的解释是服务器有某种 DOS 保护并阻止了我的请求?

知道如何解决这个问题吗?我需要实施“冷却”吗?

【问题讨论】:

  • 你可以使用setInterval,这样页面就不会挂起。

标签: javascript node.js file download


【解决方案1】:

首先,您需要一个变量来跟踪返回了哪些图像以及返回了多少。

var returnedImages = {}
var returnedCount = 0

接下来,您需要将该循环包装在一个函数中,并跳过已经下载的图像

var fetchImgs = function() {
    for (let i = 0; i < 10000; i++) {
        if(returnedImages[i]) continue;
        http.get(`http://www.example.com/${i}.png`, opt, (res) => {
            console.log(i)
            if (res.statusCode !== 200) return
            res.pipe(fs.createWriteStream(`resource/${i}.png`))
            returnedCount++
        })
    }
} 

然后您可以在 try/catch 循环中递归调用该函数

while(returnedCount < 10000) {
    try {
        returnedCount = 0
        fetchImgs()
    } catch(e) {
        if(returnedCount == 0) throw new Error("Cannot fetch anymore")
    }
}

catch 块中的 if 检查是否没有返回图像,如果是则错误输出(假设服务器不再允许来自您的 ip 的连接)。

这不是万无一失的,但是您可以根据自己的喜好对其进行调整:) 希望这会有所帮助

【讨论】:

    【解决方案2】:

    您可以使用@Werlious 提到的批处理,或者我建议您使用所有的计算能力。由于您的事务是原子的和幂等的,您可以利用这种并行方法,这也将扩展到更多的数字。

    // parent.js
    var child_process = require('child_process');
    
    var numchild = require('os').cpus().length;
    var done = 0;
    var filesListJSON = [{
        "file_name": "Blessed_Titles.jpg",
        "url": "https://i.imgur.com/FRDibHa.jpg",
        "downloadId": "6r44r4k340rvvr"
    }, {
        "file_name": "Blessed_Titles2.jpg",
        "url": "https://i.imgur.com/FRDibHa2.jpg",
        "downloadId": "6r44r4k340rvvr"
    }, {
        "file_name": "Blessed_Titles3.jpg",
        "url": "https://i.imgur.com/FRDibHa3.jpg",
        "downloadId": "6r44r4k340rvvr"
    }];
    
    // split the array into number of parallel threads avalible
    var chunks = _.chunk(filesListJSON, numchild);
    
    for (var i = 0; i < numchild; i++) {
        var
        var child = child_process.fork('./child');
        //send the chunk of the list to respective thread. 
        child.send(chunks[i]);
        //ps please check the count and logic for yourself I have not tested this.
        child.on('message', function (message) {
            console.log('[parent] received message from child:', message);
            done++;
            if (done === numchild) {
                console.log('[parent] received all results');
          ...
        }
      });
    }
    
    // child.js
    process.on('message', function (list) {
        console.log('[child] received message from server:', message);
        downloadFiles(list, function (done) {
            console.log("Done  downloading files : " + list.length);
            process.send({
                child: process.pid,
                result: done
            });
            process.disconnect();
        });
    });
    
    function downloadFiles(list, cb) {
        //loop over list
        //logic to download files
        //cb(true)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-07
      • 1970-01-01
      • 2013-01-12
      • 2018-12-04
      • 1970-01-01
      • 1970-01-01
      • 2014-05-31
      相关资源
      最近更新 更多