无法从解析服务器流视频(PFFile) [英] Cant stream video (PFFile) from parse server
问题描述
我在我的数据库中上传的PFFile网址中使用我的iOS应用流式传输视频时遇到了问题。我使用Heroku和AWS,而且我仍然遇到同样的问题。当文件托管在旧的分析服务器中时,它曾经工作得很好。
当我在Chrome浏览器中打开它时,PFFile网址可以正常工作,以下是视频的链接:
http://shuuapp.herokuapp.com/parse/files/wnQeou0L4klDelSEtMOX6SxXRVKu1f3sKl6vg349/24092609eadcc049f711aafbd59c1a18_movie.mp4
与下面的链接中提到的问题完全相同:
parse-server在Safari / iOS中似乎不支持流媒体,解决方案是使用express& GridStore如下,
parse-server-example \\\
ode_modules\parse-server\lib\Routers\FilesRouter p>
{
key:'getHandler',
value:function getHandler(req,res,content){
var config = new _Config2.default(req.params.appId);
var filesController = config.filesController;
var filename = req.params.filename;
var video ='.mp4'
var lastFourCharacters = video.substr(video.length - 4);
if(lastFourCharacters =='.mp4'){
filesController.handleVideoStream(req,res,filename).then(function(data){
} ).catch(function(err){
console.log('404FilesRouter');
res.status(404);
res.set('Content-Type','text /简单');
res.end('File not found。');
});
} else {
filesController.getFileData(config,filename).then(function(data){
res.status(200);
res.end(data);
})。catch(function(err){
res.status(404);
res.set('Content-Type','text / plain');
res .end('File not found。');
});
}
}
},...
parse-server-example\\\
ode_modules\parse-server\lib\Controllers\FilesController
_createClass(FilesController,[{
key:'getFileData',
value:function getFileData(config,filename){
return this.adapter.getFileData(filename);
}
} {
key:'handleVideoStream',
value:函数handleVideoStream(req,res,filename){
return this.adapter.handleVideoStream(req,res,filename) ;
}
},...
parse-server -example\\\
ode_modules\parse-server\lib\Adapters\Files\GridStoreAdapter
...,{
key:'handleVideoStream',
value:函数handleVideoStream(req,res,filename){
return this._connect()。then(function(database){
返回_mongodb.GridStore.exist(数据库,文件名).then( function(){
var gridStore = new _mongodb.GridStore(database,filename,'r');
gridStore.open(function(err,GridFile){
if(!GridFile){
res.send(404,'Not Found');
return;
)
console.log('filename');
StreamGridFile(GridFile,req,res);
});
});
})
}
},...
< (GridFile,req,res){
var buffer_size(GridFile,req,res){
函数StreamGridFile = 1024 * 1024; // 1024Kb
if(req.get('Range')!= null){//是:if(req.headers ['range'])
//范围请求,partialle流文件
console.log('Range Request');
var parts = req.get('Range')。replace(/ bytes = /,).split( - );
var partialstart = parts [0];
var partialend = parts [1];
var start = partialstart? parseInt(partialstart,10):0;
var end = partialend? parseInt(partialend,10):GridFile.length - 1;
var chunksize =(end - start)+ 1;
if(chunksize == 1){
start = 0;
partialend = false; ((((GridFile.length-1) - 开始)<(buffer_size)){
end = GridFile(
)
if(!partialend){
if .length - 1;
} else {
end = start +(buffer_size);
}
chunksize =(end - start)+ 1;
}
if(start == 0&& end == 2){
chunksize = 1;
$ b $ res.writeHead(206,{
'Cache-Control':'no-cache',
'Content-Range':'bytes'+ start +' - '+ end +'/'+ GridFile.length,
'Accept-Ranges':'bytes',
'Content-Length':chunksize,
'Content-Type ':'video / mp4',
});
GridFile.seek(start,function(){
//获取GridFile流
var stream = GridFile.stream(true);
var结束= false;
var bufferIdx = 0;
var bufferAvail = 0;
var range =(end - start)+ 1;
var totalbyteswanted =(end - start)+ 1;
var totalbyteswritten = 0;
//写回应
stream.on('data',function(buff){
bufferAvail + = buff.length;
//确定检查我们是否有足够的范围来覆盖我们的范围
if(bufferAvail< range){
//没有足够的字节来满足我们的全范围
if(bufferAvail> 0 )
{
//写入完整缓冲区
res.write(buff);
totalbyteswritten + = buff.length;
range - = buff.length;
bufferIdx + = b uff.length;
bufferAvail - = buff.length;
}
}
else {
//足够的字节来满足我们的全部范围!
if(bufferAvail> 0){
var buffer = buff.slice(0,range);
res.write(buffer);
totalbyteswritten + = buffer.length;
bufferIdx + = range;
bufferAvail - = range;
if(totalbyteswritten> = totalbyteswanted){
// totalbytes = 0;
GridFile.close();
res.end();
this.destroy();
}
});
});
} else {
// res.end(GridFile);
//回传整个文件
res.header('Cache-Control','no-cache');
res.header('Connection','keep-alive');
res.header(Accept-Ranges,bytes);
res.header('Content-Type','video / mp4');
res.header('Content-Length',GridFile.length);
var stream = GridFile.stream(true).pipe(res);
}
};
PS I am having trouble streaming video with my iOS app from URL of a PFFile uploaded in my database. I used Heroku and AWS and I still have the same issue. It used to work fine when the files were hosted in the old parse server. the PFFile url works fine when I open it in a chrome web browser but not in safari nor in the iOS app. the following is the link of the video:
http://shuuapp.herokuapp.com/parse/files/wnQeou0L4klDelSEtMOX6SxXRVKu1f3sKl6vg349/24092609eadcc049f711aafbd59c1a18_movie.mp4 Its exactly the same issue as the issue mentioned in the link below: iOS - Can't stream video from Parse Backend parse-server doesn't seem to be supporting streaming in Safari/iOS and the solution is the enable it using express & GridStore as follows, parse-server-example\node_modules\parse-server\lib\Routers\FilesRouter parse-server-example\node_modules\parse-server\lib\Controllers\FilesController parse-server-example\node_modules\parse-server\lib\Adapters\Files\GridStoreAdapter Bottom of GridStore Adapter P.S
The original answer is given by @Bragegs here - https://github.com/ParsePlatform/parse-server/issues/1440#issuecomment-212815625 . 这篇关于无法从解析服务器流视频(PFFile)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
原始答案由@Bragegs给出 - https://github.com/ParsePlatform/parse-server/issues/1440#issuecomment-212815625 a>。 {
key: 'getHandler',
value: function getHandler(req, res, content) {
var config = new _Config2.default(req.params.appId);
var filesController = config.filesController;
var filename = req.params.filename;
var video = '.mp4'
var lastFourCharacters = video.substr(video.length - 4);
if (lastFourCharacters == '.mp4') {
filesController.handleVideoStream(req, res, filename).then(function (data) {
}).catch(function (err) {
console.log('404FilesRouter');
res.status(404);
res.set('Content-Type', 'text/plain');
res.end('File not found.');
});
}else{
filesController.getFileData(config, filename).then(function (data) {
res.status(200);
res.end(data);
}).catch(function (err) {
res.status(404);
res.set('Content-Type', 'text/plain');
res.end('File not found.');
});
}
}
} , ...
_createClass(FilesController, [{
key: 'getFileData',
value: function getFileData(config, filename) {
return this.adapter.getFileData(filename);
}
},{
key: 'handleVideoStream',
value: function handleVideoStream(req, res, filename) {
return this.adapter.handleVideoStream(req, res, filename);
}
}, ...
... , {
key: 'handleVideoStream',
value: function handleVideoStream(req, res, filename) {
return this._connect().then(function (database) {
return _mongodb.GridStore.exist(database, filename).then(function () {
var gridStore = new _mongodb.GridStore(database, filename, 'r');
gridStore.open(function(err, GridFile) {
if(!GridFile) {
res.send(404,'Not Found');
return;
}
console.log('filename');
StreamGridFile(GridFile, req, res);
});
});
})
}
}, ...
function StreamGridFile(GridFile, req, res) {
var buffer_size = 1024 * 1024;//1024Kb
if (req.get('Range') != null) { //was: if(req.headers['range'])
// Range request, partialle stream the file
console.log('Range Request');
var parts = req.get('Range').replace(/bytes=/, "").split("-");
var partialstart = parts[0];
var partialend = parts[1];
var start = partialstart ? parseInt(partialstart, 10) : 0;
var end = partialend ? parseInt(partialend, 10) : GridFile.length - 1;
var chunksize = (end - start) + 1;
if(chunksize == 1){
start = 0;
partialend = false;
}
if(!partialend){
if(((GridFile.length-1) - start) < (buffer_size) ){
end = GridFile.length - 1;
}else{
end = start + (buffer_size);
}
chunksize = (end - start) + 1;
}
if(start == 0 && end == 2){
chunksize = 1;
}
res.writeHead(206, {
'Cache-Control': 'no-cache',
'Content-Range': 'bytes ' + start + '-' + end + '/' + GridFile.length,
'Accept-Ranges': 'bytes',
'Content-Length': chunksize,
'Content-Type': 'video/mp4',
});
GridFile.seek(start, function () {
// get GridFile stream
var stream = GridFile.stream(true);
var ended = false;
var bufferIdx = 0;
var bufferAvail = 0;
var range = (end - start) + 1;
var totalbyteswanted = (end - start) + 1;
var totalbyteswritten = 0;
// write to response
stream.on('data', function (buff) {
bufferAvail += buff.length;
//Ok check if we have enough to cover our range
if(bufferAvail < range) {
//Not enough bytes to satisfy our full range
if(bufferAvail > 0)
{
//Write full buffer
res.write(buff);
totalbyteswritten += buff.length;
range -= buff.length;
bufferIdx += buff.length;
bufferAvail -= buff.length;
}
}
else{
//Enough bytes to satisfy our full range!
if(bufferAvail > 0) {
var buffer = buff.slice(0,range);
res.write(buffer);
totalbyteswritten += buffer.length;
bufferIdx += range;
bufferAvail -= range;
}
}
if(totalbyteswritten >= totalbyteswanted) {
// totalbytes = 0;
GridFile.close();
res.end();
this.destroy();
}
});
});
}else{
// res.end(GridFile);
// stream back whole file
res.header('Cache-Control', 'no-cache');
res.header('Connection', 'keep-alive');
res.header("Accept-Ranges", "bytes");
res.header('Content-Type', 'video/mp4');
res.header('Content-Length', GridFile.length);
var stream = GridFile.stream(true).pipe(res);
}
};