@@ -4,6 +4,8 @@ import http from 'http';
4
4
import https from 'https' ;
5
5
import urlMod from 'url' ;
6
6
7
+ import { parseContentRange } from './utils' ;
8
+
7
9
8
10
function readRangeFromBlocks ( blocks , rangeOffset , rangeLength ) {
9
11
const rangeTop = rangeOffset + rangeLength ;
@@ -121,6 +123,9 @@ class BlockedSource {
121
123
122
124
// block ids waiting for a batched request. Either a Set or null
123
125
this . blockIdsAwaitingRequest = null ;
126
+
127
+ // file size to not read over. To be set when first response was set
128
+ this . fileSize = null ;
124
129
}
125
130
126
131
/**
@@ -130,7 +135,10 @@ class BlockedSource {
130
135
* @returns {ArrayBuffer } The subset of the file.
131
136
*/
132
137
async fetch ( offset , length , immediate = false ) {
133
- const top = offset + length ;
138
+ let top = offset + length ;
139
+ if ( this . fileSize !== null ) {
140
+ top = Math . min ( top , this . fileSize ) ;
141
+ }
134
142
135
143
// calculate what blocks intersect the specified range (offset + length)
136
144
// determine what blocks are already stored or beeing requested
@@ -192,6 +200,9 @@ class BlockedSource {
192
200
const o = i * this . blockSize ;
193
201
const t = Math . min ( o + this . blockSize , response . data . byteLength ) ;
194
202
const data = response . data . slice ( o , t ) ;
203
+ if ( this . fileSize === null && response . fileSize ) {
204
+ this . fileSize = response . fileSize ;
205
+ }
195
206
this . blockRequests . delete ( id ) ;
196
207
this . blocks . set ( id , {
197
208
data,
@@ -257,10 +268,17 @@ export function makeFetchSource(url, { headers = {}, blockSize } = {}) {
257
268
} else if ( response . status === 206 ) {
258
269
const data = response . arrayBuffer
259
270
? await response . arrayBuffer ( ) : ( await response . buffer ( ) ) . buffer ;
271
+
272
+ const contentRange = parseContentRange ( response . headers . get ( 'Content-Range' ) ) ;
273
+ let fileSize ;
274
+ if ( contentRange !== null ) {
275
+ fileSize = contentRange . length ;
276
+ }
260
277
return {
261
278
data,
262
279
offset,
263
280
length,
281
+ fileSize,
264
282
} ;
265
283
} else {
266
284
const data = response . arrayBuffer
@@ -269,6 +287,7 @@ export function makeFetchSource(url, { headers = {}, blockSize } = {}) {
269
287
data,
270
288
offset : 0 ,
271
289
length : data . byteLength ,
290
+ fileSize : data . byteLength ,
272
291
} ;
273
292
}
274
293
} , { blockSize } ) ;
@@ -297,16 +316,23 @@ export function makeXHRSource(url, { headers = {}, blockSize } = {}) {
297
316
request . onload = ( ) => {
298
317
const data = request . response ;
299
318
if ( request . status === 206 ) {
319
+ const contentRange = parseContentRange ( request . getResponseHeader ( 'Content-Range' ) ) ;
320
+ let fileSize ;
321
+ if ( contentRange !== null ) {
322
+ fileSize = contentRange . length ;
323
+ }
300
324
resolve ( {
301
325
data,
302
326
offset,
303
327
length,
328
+ fileSize,
304
329
} ) ;
305
330
} else {
306
331
resolve ( {
307
332
data,
308
333
offset : 0 ,
309
334
length : data . byteLength ,
335
+ fileSize : data . byteLength ,
310
336
} ) ;
311
337
}
312
338
} ;
@@ -328,10 +354,18 @@ export function makeHttpSource(url, { headers = {}, blockSize } = {}) {
328
354
return new BlockedSource ( async ( offset , length ) => new Promise ( ( resolve , reject ) => {
329
355
const parsed = urlMod . parse ( url ) ;
330
356
const request = ( parsed . protocol === 'http:' ? http : https ) . get (
331
- { ...parsed ,
357
+ {
358
+ ...parsed ,
332
359
headers : {
333
360
...headers , Range : `bytes=${ offset } -${ offset + length - 1 } ` ,
334
- } } , ( result ) => {
361
+ } ,
362
+ } ,
363
+ ( result ) => {
364
+ const contentRange = parseContentRange ( result . headers [ 'content-range' ] ) ;
365
+ let fileSize ;
366
+ if ( contentRange !== null ) {
367
+ fileSize = contentRange . length ;
368
+ }
335
369
const chunks = [ ] ;
336
370
// collect chunks
337
371
result . on ( 'data' , ( chunk ) => {
@@ -345,6 +379,7 @@ export function makeHttpSource(url, { headers = {}, blockSize } = {}) {
345
379
data,
346
380
offset,
347
381
length : data . byteLength ,
382
+ fileSize,
348
383
} ) ;
349
384
} ) ;
350
385
} ,
@@ -392,11 +427,11 @@ export function makeBufferSource(arrayBuffer) {
392
427
393
428
function closeAsync ( fd ) {
394
429
return new Promise ( ( resolve , reject ) => {
395
- close ( fd , err => {
430
+ close ( fd , ( err ) => {
396
431
if ( err ) {
397
- reject ( err )
432
+ reject ( err ) ;
398
433
} else {
399
- resolve ( )
434
+ resolve ( ) ;
400
435
}
401
436
} ) ;
402
437
} ) ;
0 commit comments