@@ -37,18 +37,14 @@ export class FilesRouter {
3737 const filesController = config . filesController ;
3838 const filename = req . params . filename ;
3939 const contentType = mime . lookup ( filename ) ;
40- if ( req . get [ 'Range' ] ) {
41- if ( typeof filesController . adapter . constructor . name !== 'undefined' ) {
42- if ( filesController . adapter . constructor . name == 'GridStoreAdapter' ) {
43- filesController . getFileRange ( config , filename ) . then ( ( gridFile ) => {
44- handleRangeRequest ( gridFile , req , res , contentType ) ;
45- } ) . catch ( ( err ) => {
46- res . status ( 404 ) ;
47- res . set ( 'Content-Type' , 'text/plain' ) ;
48- res . end ( 'File not found.' ) ;
49- } ) ;
50- }
51- }
40+ if ( isFileStreamable ( req , filesController ) ) {
41+ filesController . getFileStream ( config , filename ) . then ( ( stream ) => {
42+ handleFileStream ( stream , req , res , contentType ) ;
43+ } ) . catch ( ( err ) => {
44+ res . status ( 404 ) ;
45+ res . set ( 'Content-Type' , 'text/plain' ) ;
46+ res . end ( 'File not found.' ) ;
47+ } ) ;
5248 } else {
5349 filesController . getFileData ( config , filename ) . then ( ( data ) => {
5450 res . status ( 200 ) ;
@@ -109,14 +105,30 @@ export class FilesRouter {
109105 }
110106}
111107
112- function handleRangeRequest ( gridFile , req , res , contentType ) {
108+ function isFileStreamable ( req , filesController ) {
109+ if ( req . get [ 'Range' ] ) {
110+ if ( ! ( typeof filesController . adapter . getFileStream === 'function' ) ) {
111+ return false ;
112+ }
113+ if ( typeof filesController . adapter . constructor . name !== 'undefined' ) {
114+ if ( filesController . adapter . constructor . name == 'GridStoreAdapter' ) {
115+ return true ;
116+ }
117+ }
118+ }
119+ return false ;
120+ }
121+
122+ // handleFileStream is licenced under Creative Commons Attribution 4.0 International License (https://creativecommons.org/licenses/by/4.0/).
123+ // Author: LEROIB at weightingformypizza (https://weightingformypizza.wordpress.com/2015/06/24/stream-html5-media-content-like-video-audio-from-mongodb-using-express-and-gridstore/).
124+ function handleFileStream ( stream , req , res , contentType ) {
113125 var buffer_size = 1024 * 1024 ; //1024Kb
114126 // Range request, partiall stream the file
115127 var parts = req . get [ "Range" ] . replace ( / b y t e s = / , "" ) . split ( "-" ) ;
116128 var partialstart = parts [ 0 ] ;
117129 var partialend = parts [ 1 ] ;
118130 var start = partialstart ? parseInt ( partialstart , 10 ) : 0 ;
119- var end = partialend ? parseInt ( partialend , 10 ) : gridFile . length - 1 ;
131+ var end = partialend ? parseInt ( partialend , 10 ) : stream . length - 1 ;
120132 var chunksize = ( end - start ) + 1 ;
121133
122134 if ( chunksize == 1 ) {
@@ -125,8 +137,8 @@ function handleRangeRequest(gridFile, req, res, contentType) {
125137 }
126138
127139 if ( ! partialend ) {
128- if ( ( ( gridFile . length - 1 ) - start ) < ( buffer_size ) ) {
129- end = gridFile . length - 1 ;
140+ if ( ( ( stream . length - 1 ) - start ) < ( buffer_size ) ) {
141+ end = stream . length - 1 ;
130142 } else {
131143 end = start + ( buffer_size ) ;
132144 }
@@ -138,23 +150,23 @@ function handleRangeRequest(gridFile, req, res, contentType) {
138150 }
139151
140152 res . writeHead ( 206 , {
141- 'Content-Range' : 'bytes ' + start + '-' + end + '/' + gridFile . length ,
153+ 'Content-Range' : 'bytes ' + start + '-' + end + '/' + stream . length ,
142154 'Accept-Ranges' : 'bytes' ,
143155 'Content-Length' : chunksize ,
144156 'Content-Type' : contentType ,
145157 } ) ;
146158
147- gridFile . seek ( start , function ( ) {
159+ stream . seek ( start , function ( ) {
148160 // get gridFile stream
149- var stream = gridFile . stream ( true ) ;
161+ var gridFileStream = stream . stream ( true ) ;
150162 var ended = false ;
151163 var bufferIdx = 0 ;
152164 var bufferAvail = 0 ;
153165 var range = ( end - start ) + 1 ;
154166 var totalbyteswanted = ( end - start ) + 1 ;
155167 var totalbyteswritten = 0 ;
156168 // write to response
157- stream . on ( 'data' , function ( buff ) {
169+ gridFileStream . on ( 'data' , function ( buff ) {
158170 bufferAvail += buff . length ;
159171 //Ok check if we have enough to cover our range
160172 if ( bufferAvail < range ) {
@@ -167,7 +179,7 @@ function handleRangeRequest(gridFile, req, res, contentType) {
167179 bufferIdx += buff . length ;
168180 bufferAvail -= buff . length ;
169181 }
170- } else {
182+ } else {
171183 //Enough bytes to satisfy our full range!
172184 if ( bufferAvail > 0 ) {
173185 const buffer = buff . slice ( 0 , range ) ;
@@ -179,7 +191,7 @@ function handleRangeRequest(gridFile, req, res, contentType) {
179191 }
180192 if ( totalbyteswritten >= totalbyteswanted ) {
181193 //totalbytes = 0;
182- gridFile . close ( ) ;
194+ stream . close ( ) ;
183195 res . end ( ) ;
184196 this . destroy ( ) ;
185197 }
0 commit comments