@@ -37,18 +37,14 @@ export class FilesRouter {
37
37
const filesController = config . filesController ;
38
38
const filename = req . params . filename ;
39
39
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
+ } ) ;
52
48
} else {
53
49
filesController . getFileData ( config , filename ) . then ( ( data ) => {
54
50
res . status ( 200 ) ;
@@ -109,14 +105,30 @@ export class FilesRouter {
109
105
}
110
106
}
111
107
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 ) {
113
125
var buffer_size = 1024 * 1024 ; //1024Kb
114
126
// Range request, partiall stream the file
115
127
var parts = req . get [ "Range" ] . replace ( / b y t e s = / , "" ) . split ( "-" ) ;
116
128
var partialstart = parts [ 0 ] ;
117
129
var partialend = parts [ 1 ] ;
118
130
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 ;
120
132
var chunksize = ( end - start ) + 1 ;
121
133
122
134
if ( chunksize == 1 ) {
@@ -125,8 +137,8 @@ function handleRangeRequest(gridFile, req, res, contentType) {
125
137
}
126
138
127
139
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 ;
130
142
} else {
131
143
end = start + ( buffer_size ) ;
132
144
}
@@ -138,23 +150,23 @@ function handleRangeRequest(gridFile, req, res, contentType) {
138
150
}
139
151
140
152
res . writeHead ( 206 , {
141
- 'Content-Range' : 'bytes ' + start + '-' + end + '/' + gridFile . length ,
153
+ 'Content-Range' : 'bytes ' + start + '-' + end + '/' + stream . length ,
142
154
'Accept-Ranges' : 'bytes' ,
143
155
'Content-Length' : chunksize ,
144
156
'Content-Type' : contentType ,
145
157
} ) ;
146
158
147
- gridFile . seek ( start , function ( ) {
159
+ stream . seek ( start , function ( ) {
148
160
// get gridFile stream
149
- var stream = gridFile . stream ( true ) ;
161
+ var gridFileStream = stream . stream ( true ) ;
150
162
var ended = false ;
151
163
var bufferIdx = 0 ;
152
164
var bufferAvail = 0 ;
153
165
var range = ( end - start ) + 1 ;
154
166
var totalbyteswanted = ( end - start ) + 1 ;
155
167
var totalbyteswritten = 0 ;
156
168
// write to response
157
- stream . on ( 'data' , function ( buff ) {
169
+ gridFileStream . on ( 'data' , function ( buff ) {
158
170
bufferAvail += buff . length ;
159
171
//Ok check if we have enough to cover our range
160
172
if ( bufferAvail < range ) {
@@ -167,7 +179,7 @@ function handleRangeRequest(gridFile, req, res, contentType) {
167
179
bufferIdx += buff . length ;
168
180
bufferAvail -= buff . length ;
169
181
}
170
- } else {
182
+ } else {
171
183
//Enough bytes to satisfy our full range!
172
184
if ( bufferAvail > 0 ) {
173
185
const buffer = buff . slice ( 0 , range ) ;
@@ -179,7 +191,7 @@ function handleRangeRequest(gridFile, req, res, contentType) {
179
191
}
180
192
if ( totalbyteswritten >= totalbyteswanted ) {
181
193
//totalbytes = 0;
182
- gridFile . close ( ) ;
194
+ stream . close ( ) ;
183
195
res . end ( ) ;
184
196
this . destroy ( ) ;
185
197
}
0 commit comments