Загрузка файла с FTP-сервера на клиент с помощью Node js

#javascript #node.js #ftp

#javascript #node.js #ftp

Вопрос:

Архитектура системы

Система состоит из 3 компонентов

1: FTP-сервер: используется для хранения файлов. Может быть доступен только Node.js приложение. Нет прямого доступа.

2: Node.js : Предоставляет API для взаимодействия с FTP-сервером. Единственный способ взаимодействия с FTP-сервером. Node.js приложение не имеет коллекции файлов, хранящихся на FTP. Предоставляет только метод для работы с FTP. Node.js приложение не должно хранить какие-либо загруженные из него файлы и скачивать их с него.

3: Клиент: пользователь, как будет загружать или загружать файл на FTP-сервер с помощью Node.js приложение.

Что я сделал:

Я могу загрузить файл, хранящийся на FTP, с помощью basic-ftp package. Вот код для функции загрузки файла.

 async function downloadFile(folderPath, fileName, writeStream) {
    console.log(folderPath);
    console.log(fileName);
    const client = new ftp.Client()
    // client.ftp.verbose = true
    try {
        await client.access({
            'host': process.env.FTP_HOST,
            'user': process.env.FTP_USER,
            'password': process.env.FTP_PASSWORD,
        });
        await client.ensureDir(folderPath);
        await client.downloadTo(writeStream, fileName);
    }
    catch(err) {
        console.log(err)
    }
    client.close()
}
  

Файл загружается в каталог с именем /downloads на Node.js сервер. На самом деле я хочу загрузить файл непосредственно на клиентский компьютер. Чтобы загрузить файл непосредственно на клиент, я попробовал потоковую writeStream передачу объекта из метода загрузки. Вот код для этого

 app.post("/download/file", urlencodedParser, (req, res, next) => {
    var writeStream = fs.createWriteStream('./downloads/' req.body.fileName);
    writeStream.on("data", (data) => {
      res.write(data);
    })
    writeStream.on("close", () => {
      res.end()
    })

    res.setHeader('Transfer-Encoding', 'chunked');
    downloadFile(req.body.folderName, req.body.fileName, writeStream);
})
  

Это не работает. Это всегда заканчивается ошибкой при полной загрузке файла.

Другой подход, который я попробовал, — сгенерировать URL-адрес для файла, и клиент нажмет на URL-адрес, чтобы загрузить файл. Проблема с этим подходом заключается в том, что файл не завершен к моменту начала загрузки, что приводит к неполной загрузке файла. Например, если размер файла составляет 10 МБ и к моменту нажатия клиентом ссылки было загружено только 2 МБ, он загрузит только 2 МБ файла, а не 10 МБ.

Цель:

Загрузите файл на клиент (браузер) с FTP-сервера через узел js.

Требование:

Загрузите файл, хранящийся на FTP-сервере, непосредственно на клиент через узел js.

Ограничения:

Клиент не имеет доступа к FTP-серверу.

Единственный способ получить доступ к серверу — через приложение Node js.

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

1. Здравствуйте, итак, по сути, вы хотите «соединить» сервер (ИСПОЛЬЗУЯ NodeJS) С клиентом, чтобы клиент никогда не видел ОСНОВНОЙ сервер, только сервер NodeJS, не так ли?

2. ДА. Я хочу перейти с сервера НА клиент.

3. Я не тестировал это, но я думаю, что это можно сделать с помощью модуля «net» из nodejs, вы могли бы просто «передать» соединение с сервера клиенту, и сервер будет видеть только сервер nodejs, а клиент будет видеть только сервер nodejs! попробуйте…

4. вам просто нужно вручную включить учетные данные FTP при подключении перед каналом…

Ответ №1:

Вы можете попытаться указать res в качестве выходного потока напрямую. Таким образом, вы просто перенаправите поток с ftp на клиент:

 async function downloadFile(fileName, writeStream) {
    console.log(fileName);
    const client = new ftp.Client()
    // client.ftp.verbose = true
    try {
        await client.access({
            'host': process.env.FTP_HOST,
            'user': process.env.FTP_USER,
            'password': process.env.FTP_PASSWORD,
        });
        await client.downloadTo(writeStream, fileName);
    }
    catch(err) {
        console.log(err)
    }
    client.close()
}

app.post("/download/file", urlencodedParser, (req, res, next) => {
    downloadFile(req.body.fileName, res);
})