#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`);
});
});
});
}