как создать читаемый поток с удаленного URL-адреса в nodejs?

в документации nodejs в разделе потоков говорится, что я могу сделать fs.createReadStream(url || path). Но, когда я действительно это делаю, Он говорит мне Error: ENOENT: no such file or directory. Я просто хочу передать видео из читаемого в записываемый поток, но я застрял на создании читаемого.

мой код:

const express = require('express')
const fs = require('fs')
const url = 'https://www.example.com/path/to/mp4Video.mp4'
const port = 3000

app.get('/video', (req, res) => {
    const readable = fs.createReadStream(url)
})
app.listen(port, () => {
    console.log('listening on port ' + port)
})

ОШИБКА:

listening on port 3000
events.js:291
      throw er; // Unhandled 'error' event
      ^

Error: ENOENT: no such file or directory, open 'https://www.example.com/path/to/mp4Video.mp4'
Emitted 'error' event on ReadStream instance at:
    at internal/fs/streams.js:136:12
    at FSReqCallback.oncomplete (fs.js:156:23) {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: 'https://www.example.com/path/to/mp4Video.mp4'
}

PS: https://www.example.com/path/to/mp4Video.mp4 IS NOT THE ACTUAL URL


person Martin Wittick    schedule 31.01.2021    source источник


Ответы (1)


fs.createReadStream() не работает с URL-адресами http, только с file:// URL-адресами или путями к файлам. К сожалению, это не описано в документе fs, но если вы посмотрите на исходный код для fs.createReadStream() и следуя тому, что он вызывает, вы можете обнаружить, что он в конечном итоге вызывает fileURULtoPath(url), который выдает, если это не URL-адрес file:.

function fileURLToPath(path) {
  if (typeof path === 'string')
    path = new URL(path);
  else if (!isURLInstance(path))
    throw new ERR_INVALID_ARG_TYPE('path', ['string', 'URL'], path);
  if (path.protocol !== 'file:')
    throw new ERR_INVALID_URL_SCHEME('file');
  return isWindows ? getPathFromURLWin32(path) : getPathFromURLPosix(path);
}

Было бы предложено использовать библиотеку got(), чтобы получить поток чтения из URL-адреса:

const got = require('got');
const mp4Url = 'https://www.example.com/path/to/mp4Video.mp4';

app.get('/video', (req, res) => {
    got.stream(mp4Url).pipe(res);
});

Дополнительные примеры, описанные в этой статье: Как выполнять потоковую загрузку файлов в Nodejs с помощью Got.


Вы также можете использовать простые модули http/https для получения потока чтения, но я считаю, что got() в целом полезен на более высоком уровне для множества вещей с HTTP-запросами, поэтому я использую именно его. Но вот код с модулем https.

const https = require('https');
const mp4Url = 'https://www.example.com/path/to/mp4Video.mp4';

app.get("/", (req, res) => {
    https.get(mp4Url, (stream) => {
        stream.pipe(res);
    });
});

В обоих случаях можно добавить более продвинутую обработку ошибок.

person jfriend00    schedule 31.01.2021
comment
Версия require('https') работала очень хорошо без необходимости установки другого стороннего пакета. - person Martin Cup; 03.05.2021
comment
https.get возвращает поток? Итак, могу ли я сделать что-то вроде const myStream = https.get(mp4Url)? Я хотел бы в конечном итоге использовать это с fluent-ffmpeg. - person Optymystyc; 14.05.2021
comment
@Optymystyc - Как вы можете видеть в последнем блоке кода в моем ответе, он не возвращает поток, он предоставляет поток обратному вызову, который вы ему передаете. - person jfriend00; 14.05.2021