Не могу транслировать видео (PFFile) с сервера разбора

У меня возникают проблемы с потоковой передачей видео с помощью моего приложения для iOS по URL-адресу файла PFFile, загруженного в мою базу данных. Я использовал Heroku и AWS, и у меня все еще та же проблема. Раньше он работал нормально, когда файлы размещались на старом сервере синтаксического анализа.

URL-адрес PFFile отлично работает, когда я открываю его в веб-браузере Chrome, но не в сафари и не в приложении iOS.

ниже приведена ссылка на видео: http://shuuapp.herokuapp.com/parse/files/wnQeou0L4klDelSEtMOX6SxXRVKu1f3sKl6vg349/24092609eadcc049f711aafbd59c1a18_movie.mp4

Это точно такая же проблема, как проблема, упомянутая в ссылке ниже:

iOS — не удается передать видео из Parse Backend


person maalhammadi    schedule 04.05.2016    source источник
comment
Вы решили проблему? кажется, сервер разбора mp4 не работает. Было бы здорово, если бы вы могли ответить на свой вопрос, если вы решили его.   -  person Tobio    schedule 21.07.2016


Ответы (1)


parse-server, похоже, не поддерживает потоковую передачу в Safari/iOS, и решение заключается в том, чтобы включить его с помощью экспресс и GridStore следующим образом:

parse-server-example\node_modules\parse-server\lib\Routers\FilesRouter

    {
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.');
  });
 }
}
} , ...

parse-server-example\node_modules\parse-server\lib\Controllers\FilesController

_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);
}
}, ...

parse-server-example\node_modules\parse-server\lib\Adapters\Files\GridStoreAdapter

... , {
     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);
      });
      });
      })
      }
      }, ...

Низ адаптера GridStore

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

P.S Оригинальный ответ дан здесь @Bragegs - https://github.com/ParsePlatform/parse-server/issues/1440#issuecomment-212815625 .

person indiandragon    schedule 22.07.2016