我目前正在编写一段代码,将mp4
的视频localhost
上传到服务器。基本的是,如果视频是.mp4
,则直接上传,否则将其转换为.mp4
,然后上传。我正在使用handbrake-js
使用视频转换器。
除了一小部分,其他所有方法都工作正常。如果文件不是很大(例如小于70-80 Mb),则它就像一个魅力。但是问题出在更大的文件上。即使我在.on(end)
回调中显式调用res.end / res.send,即使在转换完成之前,我的角度控制器也会收到一些空白响应。我注意到它发生在转化率的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);
行,我也尝试了this SO article的几乎所有解决方案,但效果不佳。但仍然可以正常进行转换。
PS :另外请注意,即使对于较大的文件,转换和上传也不会出现问题,这只是我在客户端收到的响应,这让我很头疼。
更新:我尝试在VS Code中使用调试器,发现断点正好碰到res.end()
循环中的if
,该循环检查现有文件情况,但是由于某些奇怪的原因,角度控制器没有对此做出反应。而且这仅适用于较大的文件。
答案 0 :(得分:0)
我想了很久。原来Busboy
中有一个缓冲区。
在这里,我曾经这样链接busboy
和express
:
app.use(busboy());
只需将名为highWaterMark
的字段设置为大于文件大小的任意大小即可。
app.use(busboy({
highWaterMark: 2048 * 1024 * 1024, // Set buffer size in MB
}));
我不知道是什么引起了这个问题,或者我不知道新领域可以解决什么,但是,我所知道的只是可以解决的。有人可以详细说明这一点会有所帮助。