@@ -67,6 +67,116 @@ export class GridStoreAdapter extends FilesAdapter {
67
67
getFileLocation ( config , filename ) {
68
68
return ( config . mount + '/files/' + config . applicationId + '/' + encodeURIComponent ( filename ) ) ;
69
69
}
70
+
71
+ handleVideoStream ( filename , range , res , contentType ) {
72
+ return this . _connect ( ) . then ( database => {
73
+ return GridStore . exist ( database , filename )
74
+ . then ( ( ) => {
75
+ let gridStore = new GridStore ( database , filename , 'r' ) ;
76
+ gridStore . open ( ( err , gridFile ) => {
77
+ if ( ! gridFile ) {
78
+ res . status ( 404 ) ;
79
+ res . set ( 'Content-Type' , 'text/plain' ) ;
80
+ res . end ( 'File not found.' ) ;
81
+ return ;
82
+ }
83
+ streamVideo ( gridFile , range , res , contentType ) ;
84
+ } ) ;
85
+ } ) ;
86
+ } ) ;
87
+ }
88
+ }
89
+
90
+ /**
91
+ * streamVideo is licensed under Creative Commons Attribution 4.0 International License (https://creativecommons.org/licenses/by/4.0/).
92
+ * Author: LEROIB at weightingformypizza.(https://weightingformypizza.wordpress.com/2015/06/24/stream-html5-media-content-like-video-audio-from-mongodb-using-express-and-gridstore/)
93
+ */
94
+ function streamVideo ( gridFile , range , res , contentType ) {
95
+ var buffer_size = 1024 * 1024 ; //1024Kb
96
+ if ( range != null ) {
97
+ // Range request, partiall stream the file
98
+ var parts = range . replace ( / b y t e s = / , "" ) . split ( "-" ) ;
99
+ var partialstart = parts [ 0 ] ;
100
+ var partialend = parts [ 1 ] ;
101
+ var start = partialstart ? parseInt ( partialstart , 10 ) : 0 ;
102
+ var end = partialend ? parseInt ( partialend , 10 ) : gridFile . length - 1 ;
103
+ var chunksize = ( end - start ) + 1 ;
104
+
105
+ if ( chunksize == 1 ) {
106
+ start = 0 ;
107
+ partialend = false ;
108
+ }
109
+
110
+ if ( ! partialend ) {
111
+ if ( ( ( gridFile . length - 1 ) - start ) < ( buffer_size ) ) {
112
+ end = gridFile . length - 1 ;
113
+ } else {
114
+ end = start + ( buffer_size ) ;
115
+ }
116
+ chunksize = ( end - start ) + 1 ;
117
+ }
118
+
119
+ if ( start == 0 && end == 2 ) {
120
+ chunksize = 1 ;
121
+ }
122
+
123
+ res . writeHead ( 206 , {
124
+ 'Content-Range' : 'bytes ' + start + '-' + end + '/' + gridFile . length ,
125
+ 'Accept-Ranges' : 'bytes' ,
126
+ 'Content-Length' : chunksize ,
127
+ 'Content-Type' : contentType ,
128
+ } ) ;
129
+
130
+ gridFile . seek ( start , function ( ) {
131
+ // get gridFile stream
132
+ var stream = gridFile . stream ( true ) ;
133
+ var ended = false ;
134
+ var bufferIdx = 0 ;
135
+ var bufferAvail = 0 ;
136
+ var range = ( end - start ) + 1 ;
137
+ var totalbyteswanted = ( end - start ) + 1 ;
138
+ var totalbyteswritten = 0 ;
139
+ // write to response
140
+ stream . on ( 'data' , function ( buff ) {
141
+ bufferAvail += buff . length ;
142
+ //Ok check if we have enough to cover our range
143
+ if ( bufferAvail < range ) {
144
+ //Not enough bytes to satisfy our full range
145
+ if ( bufferAvail > 0 )
146
+ {
147
+ //Write full buffer
148
+ res . write ( buff ) ;
149
+ totalbyteswritten += buff . length ;
150
+ range -= buff . length ;
151
+ bufferIdx += buff . length ;
152
+ bufferAvail -= buff . length ;
153
+ }
154
+ }
155
+ else {
156
+ //Enough bytes to satisfy our full range!
157
+ if ( bufferAvail > 0 ) {
158
+ var buffer = buff . slice ( 0 , range ) ;
159
+ res . write ( buffer ) ;
160
+ totalbyteswritten += buffer . length ;
161
+ bufferIdx += range ;
162
+ bufferAvail -= range ;
163
+ }
164
+ }
165
+ if ( totalbyteswritten >= totalbyteswanted ) {
166
+ // totalbytes = 0;
167
+ gridFile . close ( ) ;
168
+ res . end ( ) ;
169
+ this . destroy ( ) ;
170
+ }
171
+ } ) ;
172
+ } ) ;
173
+ } else {
174
+ // stream back whole file
175
+ res . header ( "Accept-Ranges" , "bytes" ) ;
176
+ res . header ( 'Content-Type' , contentType ) ;
177
+ res . header ( 'Content-Length' , gridFile . length ) ;
178
+ var stream = gridFile . stream ( true ) . pipe ( res ) ;
179
+ }
70
180
}
71
181
72
182
export default GridStoreAdapter ;
0 commit comments