Как скачать содержимое каталога через ftp с помощью nodejs? - PullRequest
0 голосов
/ 08 апреля 2019

Итак, я пытаюсь загрузить содержимое каталога через sftp, используя nodejs, и до сих пор застреваю с ошибкой.

Я использую пакет ssh2-sftp-client npm и по большей части он работает довольно хорошо, так как я могу подключиться к серверу и вывести список файлов в определенном удаленном каталоге.

Использование метода fastGet для загрузки файла также работает без каких-либо хлопот, и, поскольку все методы основаны на обещаниях, я предположил, что могу достаточно легко загрузить все файлы в каталоге, выполнив что-то вроде:

let main = async () => {
    await sftp.connect(config.sftp);
    let data = await sftp.list(config.remote_dir);
    if (data.length) data.map(async x => {
        await sftp.fastGet(`${config.remote_dir}/${x.name}`, config.base_path + x.name);
    });
}

Получается, что приведенный выше код успешно загружает первый файл, но затем вылетает со следующим сообщением об ошибке:

Ошибка: не удалось получить sandbox / demo2.txt: Запрошенная операция не может быть выполнена, поскольку выполняется передача файла.

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

Я попытался использовать более традиционный метод get (), но он использует потоки, и он завершился неудачно с другой ошибкой. После исследования кажется, что произошли серьезные изменения в отношении потоков в узле 10.x. в моем случае вызов get просто не удался (даже не загружая первый файл).

Кто-нибудь знает обходной путь к этому? или другой пакет, который может загружать несколько файлов по sftp?

Спасибо!

1 Ответ

0 голосов
/ 15 апреля 2019

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

let getFromFtp = async (arr) => {
    if (arr.length == 0) return (processFiles());
    let x = arr.shift();
    conns.push(new Client());
    let idx = conns.length - 1;
    await conns[idx].connect(config.sftp.auth);
    await conns[idx]
      .fastGet(`${config.sftp.remote_dir}/${x.name}`, `${config.dl_dir}${x.name}`);
    await connections[idx].end();
    getFromFtp(arr);
};

Примечания об этой функции:

  • Параметр массива представляет собой список файлов для загрузки, предположительно извлекаемых с использованием list () заранее

  • conns был объявлен как пустой массив и используется для хранения наших клиентов.

  • с использованием array.prototype.shift (), чтобы постепенно истощать массив при прохождении списка файлов

  • метод processFiles () запускается после загрузки всех файлов.

  • это просто версия POC. Конечно, мы должны добавить к этому управление ошибками.

...