В настоящее время я работаю над фрагментом кода, который загружает mp4
видео с моего localhost
на сервер.Основным является то, что если видео является .mp4
, оно загружается напрямую, в противном случае оно преобразуется в .mp4
и затем загружается.Я использую видео конвертер, используя handbrake-js
.
Все работает отлично, за исключением крошечной части.Когда файл не такой большой, скажем, менее 70-80 Мб, он работает как шарм.Но проблема в больших файлах.Несмотря на то, что я явно вызываю res.end / res.send в обратном вызове .on(end)
, я получаю некоторый пустой ответ в своем угловом контроллере, даже до того, как преобразование завершено.Я заметил, что это происходит на 30-40% конверсии.Он имеет readystate
, равный XMLHttpRequest.DONE
, а также status = 200
.
Вот код стороны узла:
try {
if (fs.existsSync(uploadPath + filename.substring(0, filename.lastIndexOf('.')) + '.mp4')) {
res.end('<b><i>' + filename + '</i></b> already exists in the directory.');
}
else {
const fstream = fs.createWriteStream(path.join(cfg.tempStoragePath, filename));
file.pipe(fstream);
console.log("\nfile_type: " + file_type);
filename = filename.substring(0, filename.lastIndexOf('.'));
// On finish of the copying file to temp location
fstream.on('close', () => {
hbjs.spawn({
input: cfg.tempStoragePath + filename + '.' + file_type,
output: uploadPath + filename + '.mp4'
})
.on('error', err => {
// invalid user input, no video found etc
console.log('error! No input video found at: \n: ' + cfg.tempStoragePath + filename + '.' + file_type);
res.send('Conversion of the file, <b><i>' + filename + '</i></b>, from <b>.' + file_type + '</b>' + ' to <b>.mp4</b> failed because no input video was found at: \n: ' + cfg.tempStoragePath + filename + '.' + file_type);
})
.on('progress', progress => {
progress_percent = (Number(progress.percentComplete) * 2 <= 100) ? Number(progress.percentComplete) * 2 : 100;
eta = progress.eta.split(/[a-zA-Z]/);
minutes = ((+eta[0]) * 60 + (+eta[1])) / 2;
console.log('Percent complete: %d, ETA: %d ///// %s ==> mp4', progress_percent, minutes, file_type);
})
.on('end', end => {
console.log('Conversion from .' + file_type + ' to .mp4 complete.');
//delete the temp file
fs.unlink(cfg.tempStoragePath + filename + '.' + file_type);
let new_path = uploadPath + filename + '.mp4';
let stat = fs.statSync(new_path);
console.log(`Upload of '${filename}' finished`);
if(Number(progress_percent) === Number(100))
res.send('The file, <b><i>' + filename + '</i></b>, has been converted from <b>.' + file_type + '</b>' + ' to <b>.mp4</b> complete.');
})
});
}
}
catch (err) {
res.end(err);
}
Ниже приведена часть моего углового контроллера:
request = new XMLHttpRequest();
request.onreadystatechange = function () {
if (request.readyState === XMLHttpRequest.DONE && request.status === 200) {
showConversionModal('<p>' + request.responseText + '</p>', 'done');
}
};
showSomeModal('something');
request.open("POST", client.clientHost + ":" + client.clientPort + "/uploadVideoService");
formData = new FormData();
formData.append("file", files[0], files[0].name);
request.send(formData);
ПРИМЕЧАНИЕ : Все данные, которые делают console.log()
внутри узла, соответствуют ожидаемым.И даже res.end/send
отлично работает для небольших файлов, которые занимают меньше времени.Но проблема возникает только для тех, чье преобразование занимает больше времени, чем файлы меньшего размера.
Кроме того, цикл if
, который проверяет существующий файловый сценарий, не работает должным образом для этих больших файлов.Я думал, по крайней мере, это должно сработать, потому что это даже не входит в часть handbrake
.Но это не так.
И в браузере я получаю эту ошибку:
Failed to load resource: net::ERR_CONNECTION_RESET
, которая указывает на request.send(formData);
линии, и я также попробовал почти все решения из этой статьи SO , но безрезультатно.Но, тем не менее, преобразование происходит нормально.
PS : также обратите внимание, что преобразование и загрузка происходят без проблем даже для больших файлов, это просто ответ, который я получаю на клиентесторона, которая была моей головной болью.
ОБНОВЛЕНИЕ: Я попытался использовать отладчик в VS Code и увидел, что точки останова справедливо достигают res.end()
внутри цикла if
, который проверяетдля существующего файлового сценария, но по какой-то странной причине угловой контроллер не реагирует на это.И это происходит только для больших файлов.