Как я могу записать файл в mpeg movie file на диск в правильном формате?

#javascript #node.js #encoding #stream

#javascript #node.js #кодирование #поток

Вопрос:

Я пытаюсь загрузить внешний файл ts (mpeg) и записать его на диск, но я не могу понять, как я могу правильно отформатировать содержимое файла.

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

Код, который записывает файл, не подлежащий воспроизведению:

 getFile = (url) => {
  https.get(url, r => {
    let rawData = [];

    r.on("data", chunk => {
      rawData  = chunk;
    });

    r.on("end", () => {
      fs.writeFile(`./resources/test.ts`, rawData, "utf-8", err => {
        if (err) {
          console.log(`error writing file`);
          return;
        }

        console.log(`Wrote successfully`);
      });
    });
  });
};
  

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

Ответ №1:

Кодировка UTF-8 дополняет байты, в которых установлен самый значимый бит, что приводит к повреждению двоичных файлов. Вы можете сохранить это на диск без буферизации всех данных, вызвав res.pipe() Writable поток, созданный fs.createWriteStream() :

 getFile = url =>
  https.get(url, res => {
    res.pipe(fs.createWriteStream('./resources/test.ts', 'binary'))
      .on('error', console.error)
      .on('finish', () => { console.log('wrote successfully') })
  })
  

Если вы хотите, чтобы вызывающий абонент мог определить, когда загрузка завершена и произошла ли ошибка, вы можете обернуть возвращаемое значение в Promise и использовать stream.finished() :

 const { finished } = require('stream')
const getFile = url => new Promise((resolve, reject) => {
  https.get(url, res => {
    const stream = res.pipe(
      fs.createWriteStream('./resources/test.ts', 'binary')
    )

    finished(stream, err => {
      if (err) reject(err)
      else resolve()
    })
  })
})

// usage
getFile('some url').then(() => {
  console.log('wrote successfully')
}, error => {
  console.error(error)
})
  

Ответ №2:

Поскольку вы запрашиваете двоичные данные, вы должны соответствующим образом установить кодировку в ответе и при вызове WriteFile. Кодировкой по умолчанию является utf-8, что, вероятно, вызывает проблему здесь. Вы могли бы попробовать что-то вроде:

 getFile = (url) => {
    https.get(url, r => {
        let rawData = '';
        r.setEncoding('binary');

        r.on('data', chunk => {
            rawData  = chunk;
        });

        r.on('end', () => {
            fs.writeFile(`./resources/test.ts`, rawData, 'binary', err => {
                if (err) {
                    console.log(`error writing file`);
                    return;
                }

                console.log(`Wrote successfully`);
            });
        });
    });
}