Skip to content

Instantly share code, notes, and snippets.

@LautaroJayat
Created January 30, 2020 19:09
Show Gist options
  • Save LautaroJayat/79c489cb721202bd34471b85aabdb514 to your computer and use it in GitHub Desktop.
Save LautaroJayat/79c489cb721202bd34471b85aabdb514 to your computer and use it in GitHub Desktop.
ctrl.forVideo(req,res);
ctrl.forVideo = function (req, res) {
// First we store our file name in a variable using a inmediatly-invoked function
let file = (function () {
// Split the URL in each slash "/";
let splitted = req.url.split('/');
// Then we return only the last part of that array.
return splitted[splitted.length - 1];
})();
// Then we check the file stats.
// We know that it will be in /public/media,
// so we only add the file name to the string
fs.stat('public/media/' + file, (err, data) => {
// First we check for error
if (err) {
//If error, we send a response with status code 404.
res.writeHead(404)
res.end();
throw err
} else {
//In case that everithing went OK
//We check for 'range' header;
//If we find them, we procced
if (req.headers['range']) {
// We store the header in a variable
let range = req.headers['range'];
// Then we remove the first part and split the string in every dash "-"
var array = range.replace('bytes=', "").split("-");
// After that we store the number where we start to read our buffer;
var start = parseInt(array[0], 10);
// We check if there is and end, if not, we just send the total size of the file
// Total size is total -1, because we start counting from the 0.
// data.size returns the size, "data" is the object that fs.stat outputs.
var end = array[1] ? parseInt(array[1], 10) : data.size - 1;
// Here we decide the size of every chunck we will be sending
var chunck = 1024 * 1000;
// And then we set the headers and status code 206
res.writeHead(206, {
// We tell the units that we use to messure the ranges
'Accept-Ranges': 'bytes',
// We tell the range of the content that we are sending
"Content-Range": "bytes " + start + "-" + end + "/" + data.size,
// Tell the length of the chunck. We use this to control the flow of the stream.
// The "chunck" is a variable that we set in line 38 of this gist.
'Content-Length': chunck,
// Set the MIME-type
'Content-Type': 'video/mp4',
// And also set that we dont want to cache out file
// This is just to make our example work as if allways were the first time we ask the file.
'Cache-Control': 'no-cache'
});
// If the ranges headers can't be fulfilled, we will be sending a stream anyway,
// but the browser will need to assume things and slow down the process.
// Time to make our readable stream
// First we create a readableStream and store in a variable
// We pass the start and end parameters so NodeJS can know wich part needs to read and send as buffer.
let readable = fs.createReadStream('public/media/banjo.mp4', { start, end });
// If for some reason we cant create our Readable Strea, we end the response.
if (readable == null) {
console.log('readable = null');
return res.end();
// If not...
} else {
// First we use the event .on('open') to listen when the readable is ready to rock
// Then we provide a function to pipe to res.
readable.on('open', () => {
console.log('we are on open');
// This function is esential. Here we are puting all the buffer chunk to the response object.
readable.pipe(res);
});
// We also be waiting for that umpleasing error event.
readable.on('error', (err) => {
// If it happen, we will send the error with the .end() method.
res.end(err);
console.log(err);
});
}
}
}
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment