Support for reading byte ranges from files using fs.createReadStream.
This commit is contained in:
parent
56f200af5d
commit
f5f7cb9264
@ -1583,6 +1583,14 @@ Returns a new ReadStream object (See `Readable Stream`).
|
||||
, 'bufferSize': 4 * 1024
|
||||
}
|
||||
|
||||
`options` can include `start` and `end` values to read a range of bytes from
|
||||
the file instead of the entire file. Both `start` and `end` are inclusive and
|
||||
start at 0. When used, both the limits must be specified always.
|
||||
|
||||
An example to read the last 10 bytes of a file which is 100 bytes long:
|
||||
|
||||
fs.createReadStream('sample.txt', {start: 90, end: 99});
|
||||
|
||||
|
||||
## fs.WriteStream
|
||||
|
||||
|
25
lib/fs.js
25
lib/fs.js
@ -615,6 +615,16 @@ var ReadStream = fs.ReadStream = function(path, options) {
|
||||
this[key] = options[key];
|
||||
}
|
||||
|
||||
if(this.start || this.end) {
|
||||
if(this.start === undefined || this.end === undefined) {
|
||||
self.emit('error', new Error('Both start and end are needed for range streaming.'));
|
||||
} else if(this.start > this.end) {
|
||||
self.emit('error', new Error('start must be <= end'));
|
||||
} else {
|
||||
this.firstRead = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fd !== null) {
|
||||
return;
|
||||
}
|
||||
@ -653,6 +663,11 @@ ReadStream.prototype._read = function () {
|
||||
allocNewPool();
|
||||
}
|
||||
|
||||
if(this.start && this.firstRead) {
|
||||
this.pos = this.start;
|
||||
this.firstRead = false;
|
||||
}
|
||||
|
||||
// Grab another reference to the pool in the case that while we're in the
|
||||
// thread pool another read() finishes up the pool, and allocates a new
|
||||
// one.
|
||||
@ -660,6 +675,10 @@ ReadStream.prototype._read = function () {
|
||||
var toRead = Math.min(pool.length - pool.used, this.bufferSize);
|
||||
var start = pool.used;
|
||||
|
||||
if(this.pos) {
|
||||
toRead = Math.min(this.end - this.pos + 1, toRead);
|
||||
}
|
||||
|
||||
function afterRead (err, bytesRead) {
|
||||
if (err) {
|
||||
self.emit('error', err);
|
||||
@ -692,7 +711,11 @@ ReadStream.prototype._read = function () {
|
||||
self._read();
|
||||
}
|
||||
|
||||
fs.read(self.fd, pool, pool.used, toRead, undefined, afterRead);
|
||||
fs.read(self.fd, pool, pool.used, toRead, this.pos, afterRead);
|
||||
|
||||
if(self.pos) {
|
||||
self.pos += toRead;
|
||||
}
|
||||
pool.used += toRead;
|
||||
};
|
||||
|
||||
|
@ -9,6 +9,7 @@ Buffer = require('buffer').Buffer;
|
||||
path = require('path');
|
||||
fs = require('fs');
|
||||
fn = path.join(common.fixturesDir, 'elipses.txt');
|
||||
rangeFile = path.join(common.fixturesDir, 'x.txt');
|
||||
|
||||
callbacks = { open: 0, end: 0, close: 0, destroy: 0 };
|
||||
|
||||
@ -86,3 +87,12 @@ process.addListener('exit', function() {
|
||||
assert.equal(30000, file.length);
|
||||
assert.equal(10000, file3.length);
|
||||
});
|
||||
|
||||
var file4 = fs.createReadStream(rangeFile, {start: 1, end: 2});
|
||||
var contentRead = '';
|
||||
file4.addListener('data', function(data) {
|
||||
contentRead += data.toString('utf-8');
|
||||
});
|
||||
file4.addListener('end', function(data) {
|
||||
assert.equal(contentRead, 'yz');
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user