Узел JS - Невозможно получить потоковые данные без конвейера по обещанию ftp - PullRequest
0 голосов
/ 30 октября 2018

Привет, ребята. У меня проблема с моим API-интерфейсом Node.js.

Я использую -> Обещание-ftp (https://www.npmjs.com/package/promise-ftp).

Вот так выглядит конечная точка:

getData = (req, res, next) => {
  const ftp = new PromiseFtp();
  let data = [];
  ftp.connect({host: 'xxxl',user: 'xxx',password: 'xxx'})
  .then(() => {
      return ftp.get('xxx.pdf');
    }).then((stream) => {
      return new Promise((resolve, reject) => {
        stream.once('close', resolve);
        stream.once('error', reject);
        stream.pipe(fs.createReadStream('test.pdf'));
        
        stream
        .on('error', (err) => {
          return res.send({errorMessage: err});
        })
        .on('data', (chunk) => data.push(chunk))
        .on('end', () => {
          const buffer = Buffer.concat(data);
          label = buffer.toString('base64');
          
          return res.send(label);
         });
      });
    }).then(() => {
      return ftp.end();
    });
}

Проблема в том, что я не хочу сохранять этот файл рядом с файлами API, и когда я удаляю строку stream.pipe(fs.createReadStream('test.pdf'));, он не работает.

Я не уверен, что здесь делает труба.

Можете ли вы помочь мне?

1 Ответ

0 голосов
/ 30 октября 2018

readable.pipe(writable) является частью потокового API узла, который прозрачно записывает данные, которые считываются из читаемого в поток для записи, обрабатывая обратное давление для вас. Передача данных в файловую систему не требуется, и объект Express Response реализует интерфейс потока с возможностью записи, поэтому вы можете просто направить поток, возвращенный из обещания FTP, непосредственно в объект res.

getData = async (req, res) => {
  const ftp = new PromiseFtp();
  try {
    await ftp.connect({host: 'xxxl',user: 'xxx',password: 'xxx'});
    const stream = await ftp.get('xxx.pdf');
    res.type('pdf');
    await new Promise((resolve, reject) => {
      res.on('finish', resolve);
      stream.once('error', reject);
      stream.pipe(res);
    });
  } catch(e) {
    console.error(e);
  } finally {
    await ftp.end();
  }
}

Если у вас нет версии Node, поддерживающей async / await, вот версия для Promise:

getData = (req, res) => {
  const ftp = new PromiseFtp();
  ftp
    .connect({host: 'xxxl',user: 'xxx',password: 'xxx'})
    .then(() => ftp.get('xxx.pdf'))
    .then(stream => {
      res.type('pdf');
      return new Promise((resolve, reject) => {
        res.on('finish', resolve);
        stream.once('error', reject);
        stream.pipe(res);
      });
    })
    .catch(e => {
      console.error(e);
    })
    .finally(() => ftp.end());
}

Здесь у вас есть хороший вариант использования метода finally() Promise или блока try/catch/finally, который будет гарантировать, что ftp.end() вызывается, даже если происходит ошибка или нет.

Обратите внимание, что я намеренно исключил отправку ошибки клиентам, поскольку такие действия могут привести к утечке конфиденциальной информации. Лучшее решение - настроить правильное ведение журнала на стороне сервера с контекстом запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...