1

I'm trying to build a very basic video uploading system with gridfs-stream. It does work on desktop, but only partially on my phone (iOS9 iphone 5, using Chrome browser).

It works perfectly using the direct recording iOS feature (recording a video that is not in the photo gallery and without saving it), but when I try to choose a saved video in the photo gallery, the video is not uploaded properly.

  • When saved to the temp directory before being written to the database, the file is empty (size: 0kb)
  • No chunks are saved in the fs.chunks collection
  • The "length" attribute in the fs.files collection is 0
  • It doesn't display, just as if the file didn't exist.

Here is the code:

function saveVideo(file){
    var name         = file.filename.split('.').slice(0, -1),
        extension    = file.filename.split('.').pop(),
        randomString = Math.random().toString(36).substring(7);

    file.filename = name + '_' + randomString + '.' + extension;

    var writeStream = gridFs.createWriteStream({
        filename: file.filename,
        metadata: {
            validated: false
        }
    });

    fs.createReadStream(file.file).pipe(writeStream);

    writeStream.on('close', function(){
        fs.unlink(file.file);
    });
}

app.post('/addVideo', function(req, res){
    var files = req.files['file-input'];

    if (files.length){
        files.forEach(function (file, index){
            saveVideo(file);

            if (index == files.length - 1){
                res.redirect('/admin')
            }
        });
    }

    else {
        if (files.filename){
            saveVideo(files);
        }

        res.redirect('/admin');
    }
 });

app.get('/videos/:filename', function(req, res){
    gridFs.exist({'filename': req.params.filename}, function(err, found){
        if (err){
            return next(err);
        }

        if (found){
            var readStream = gridFs.createReadStream({
                filename: req.params.filename
            });

            readStream.pipe(res);
        }

        else {
             res.status(404).send('Not Found');
        }
     });
 });

Things I've thought about:

  • Using photos instead of videos does work, but I need my webapp to be able to receive videos.

  • Maybe there is a difference between direct recording and choosing a video from the gallery? I really don't understand because apart from the name that is automatically assigned by iOS, I don't see any. I tried to force a specific mimetype/encoding, but I wasn't really sure how to do it and didn't manage to make it work. (I'm not even sure how it works to be honest)

  • Using another browser: strangely, when using Safari instead of Chrome mobile, the file is properly put into the temp directory before being written to the database. It is not properly displayed afterward (the video doesn't have the right size and there's the black background placeholder just like if the video didn't exist, but I can right click the link in the chrome inspector and open it in a new window, resulting in a file download. The video is not corrupted, the file is not "empty" nor is the length attribute in the database as it is when uploading from Chrome (the video does works).

  • If it can help, when submitting my form on Chrome using the direct recording feature, it reloads the page and the input is empty. When choosing a file from the gallery, it takes a little bit more time but it doesn't reloads the page and the file is still in the input, just as if it didn't do anything. The loading bar does appear and stops in the middle. This is the code I'm using. I tried multiple versions (using the capture attribute for example), but it didn't work. I'm using the express-busboy module to decode the form's data.

<form action="/addVideo" method="POST" enctype="multipart/form-data">
  <input type="file" accept="video/*" multiple name="file-input"/>
  <input type="submit"/>
</form>
  • I tried using connect-busboy module instead of express-busboy (it doesn't write files before adding them, it directly streams it to the db), but the problem still happens.

Thanks.

TomB
  • 11
  • 3

0 Answers0