Node.js stream / pipe file larger than 2 MB results in a canceled GET request

I am trying to transfer media files (.mkv) to Node.js using fs.createReadStream (). This is great for files less than 2 MB in size, they load correctly as src of the corresponding HTML video elements.

For media files larger than 2 MB, this does not work. They do not load. On the "Network Console" tab, the GET request shows the status "(canceled)" after ~ 30 KB of data transferred. The strange part is that the video element seems to show the correct duration of the media file.

Request Method:GET
Status Code:206 Partial Content

Request header

Accept:*/*
Accept-Encoding:identity;q=1, *;q=0
Accept-Language:nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4,de;q=0.2,el;q=0.2
Connection:keep-alive
Host:(...)
Range:bytes=0-
Referer:yaddayadda
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36

Answer Headers

Accept-Ranges:bytes
Access-Control-Allow-Headers:origin, content-type
Access-Control-Allow-Methods:POST, GET, OPTIONS, DELETE
Access-Control-Allow-Origin:*
Connection:keep-alive
Content-Length:5716684
Content-Range:bytes 0-5716683/5716684
Content-Type:video/mp4
Date:Tue, 19 Nov 2013 16:29:51 GMT
X-Powered-By:Express

Server code

app.get('/getStream/:u/:f', function(req, res) {
    "use strict";
    var userId = req.params.u;
    var file = req.params.f;
    var path = "/tmp/" + userId + "/" + file;
    var stat = fs.statSync(path);
    var total = stat.size;
    if (req.headers['range']) {
        var range = req.headers.range;
        var parts = range.replace(/bytes=/, "").split("-");
        var partialstart = parts[0];
        var partialend = parts[1];

        var start = parseInt(partialstart, 10);
        var end = partialend ? parseInt(partialend, 10) : total - 1;
        var chunksize = (end - start) + 1;
        console.log('RANGE: ' + start + ' - ' + end + ' = ' + chunksize);

        var file = fs.createReadStream(path, {start: start, end: end});
        res.writeHead(206, {'Content-Range': 'bytes ' + start + '-' + end + '/' + total, 'Accept-Ranges': 'bytes', 'Content-Length': chunksize, 'Content-Type': 'video/mp4'});
        file.pipe(res);
    } else {
        console.log('ALL: ' + total);
        res.writeHead(200, {'Content-Length': total, 'Content-Type': 'video/mp4'});
        fs.createReadStream(path).pipe(res);
    }
});

Server Notes

I tried with simple stream.pipe (res), but the problem persists.

Hope I have included enough information.

Thank you in advance

+4

All Articles