Загрузка нескольких файлов с URL-адреса с помощью NodeJS

#javascript #node.js

Вопрос:

Я пытаюсь загрузить более 10 000 изображений с CDN-сервера. Однако, когда я использовал следующий код, скрипт просто создает кучу пустых файлов, и загружается только последний. Кроме того, я получил массу ошибок, в том числе MaxListenersExceededWarning и EMFILE, слишком много открытых файлов. Как решить эту проблему? Спасибо.

 const http = require('https'); // or 'https' for https:// URLs
const fs = require('fs');

for (let i = 1; i <= 500; i  ) {

var random = Math.floor(Math.random() * 1497791);
var url = "https://cdnpath.com"   random   ".png";
//var dest = "D:/SavePath/"   random   ".png";

    var file = fs.createWriteStream("D:/SavePath/#"   i   ".png");
    var request = http.get(url, function(response) {
        response.pipe(file).end();
    });
setTimeout(sleep, 3000);
}
 

Ответ №1:

Я включаю только соответствующий код. Проблема в том, что асинхронные функции не будут блокировать поток выполнения, ожидающий завершения, прежде чем продолжить выполнение. Это означает, что вы увеличите значение в цикле и получите значение 500 за меньшее время, необходимое для завершения асинхронных операций, поэтому в конце вы запишете только последнее содержимое файла

Это может решить вашу проблему

 const saveFile = (counter, rndNumber) => {
    var url = "https://cdnpath.com"   random   ".png";
    var file = fs.createWriteStream("D:/SavePath/#"   counter   ".png");
    http.get(url, function(response) {
            response.pipe(file).end();
    });
}
for (let i = 1; i <= 500; i  ) {
    var random = Math.floor(Math.random() * 1497791);
    saveFile(i, random);
}
 

Это может вызвать проблемы с перегрузкой на сервере, поэтому вы можете использовать лучший подход, используя async/await или обещания в своем коде, чтобы ограничить количество одновременных вызовов на сервер.

Комментарии:

1. Попробовал это решение, но получил ошибку [ERR_STREAM_WRITE_AFTER_END]: запись после завершения в потоке записи. Доступно для записи. запись (внутренние/потоки/доступные для записи.js:292:11) в IncomingMessage.ondata (внутренние/потоки/читаемые.js:726:22) в IncomingMessage.emit (события.js:400:28) в IncomingMessage. Читается.считывается (внутренний/потоки/читаемый.js:500:10) в потоке (внутренний/потоки/читаемый.js:982:34)

2. Я отредактировал пример, похоже, что fs.createWriteStream также является асинхронной функцией, и вам нужно дождаться завершения создания, прежде чем вызывать URL-адрес и писать ответ. Было бы проще помочь, если бы вы предоставили пример работы jsfiddler с вашим кодом

3. Ошибка типа: fs.createWriteStream(…).тогда это не функция в файле сохранения (D:Minecraftapp.js:7:63)

4. У меня была ошибка с переменной i, можете ли вы попробовать это сейчас? replit.com/languages/nodejs Я проверил это здесь и, кажется, работает