UNPKG

sgapps-server

Version:
109 lines (91 loc) 2.96 kB
/** * @private * @param {SGAppsServerRequest} request * @param {SGAppsServerResponse} response * @param {SGAppsServer} server * @param {function} callback */ function ResponsePipeFileDecorator(request, response, server, callback) { if (request === null || response === null) { callback(); return; } /** * @memberof SGAppsServerResponse# * @method pipeFile * @param {string} filePath * @param {SGAppsServerErrorOnlyCallback} callback represents a `Function(Error)` */ response.pipeFile = function ResponsePipe(filePath, callback) { var returned = false; var _callback = function (err) { if (!returned && callback) callback(err); }; if (response._flags.finished) { _callback(Error('Response is already ended')); return; } server._fs.stat(filePath, function (err, stat) { if (err) { _callback(err); return; } let readStream, start, end, total = stat.size, chunkSize; if (request.request) { var range = request.request.headers.range || ""; if (range && total) { var parts = range.replace(/bytes=/, "").split("-"); var partialStart = parts[0]; var partialEnd = parts[1]; start = parseInt(partialStart, 10); end = partialEnd ? parseInt(partialEnd, 10) : total-1; chunkSize = (end-start)+1; if ( !response.response.headersSent && !response._flags.finished ) { response.response.statusCode = 206; response.response.setHeader( "Content-Range", `bytes ${start}-${end}/${total}` ); response.response.setHeader("Accept-Ranges", "bytes"); response.response.setHeader("Content-Length", chunkSize); } } } if (typeof(start) === "number") { if (typeof(end) === "number") { readStream = server._fs.createReadStream(filePath, { start: start, end: end }); } else { readStream = server._fs.createReadStream(filePath, { start: start }); } } else { readStream = server._fs.createReadStream(filePath); } // This catches any errors that happen while creating the readable stream (usually invalid names) readStream.on('error', function(err) { _callback(err); }); // // This will wait until we know the readable stream is actually valid before piping readStream.on('open', function () { // This just pipes the read stream to the response object (which goes to the client) readStream.pipe(response.response); }); response.response.on('close', function() { // Resume the read stream when the write stream gets hungry readStream.destroy(); }); response.response.on('end', function() { // Resume the read stream when the write stream gets hungry readStream.destroy(); }); readStream.on('end', function() { _callback(null); }); }); }; // response._destroy.push(function ResponsePipeEnd() { // delete response.pipeFile; // }); callback(); }; module.exports = ResponsePipeFileDecorator;