readable-blob-stream
Version:
Read W3C Blob & File objects as a Node stream. Very useful with "browserify" and "primus" with "ejson" using pipe()
135 lines (109 loc) • 3.5 kB
JavaScript
var Readable = require('stream').Readable;
// When required from browserify, Buffer is also an Uint8Array, which is important for ejson.
var inherits = require('inherits');
var FileReader = global.FileReader;
var Uint8Array = global.Uint8Array;
/**
* Read W3C Blob & File objects as a Node stream.
* @param {Blob} blob
* @constructor
*/
function ReadableBlobStream(blob, opts)
{
if (!(this instanceof ReadableBlobStream)) {
return new ReadableBlobStream(blob, opts);
}
opts = opts || {};
opts.objectMode = false;
Readable.call(this, opts);
if (!blob)
{
throw Error('Missing argument "blob"');
}
if (typeof blob.slice !== 'function')
{
throw Error('Given argument "blob" is not really a Blob/File or your environment does not support .slice()');
}
if (!FileReader)
{
throw Error('Your environment does not support FileReader');
}
if (!Uint8Array)
{
throw Error('Your environment does not support Uint8Array');
}
this.totalSize = blob.size;
this._blob = blob;
this._nextByteStart = 0;
}
module.exports = ReadableBlobStream;
inherits(ReadableBlobStream, Readable);
function uint8ArrayToBuffer(buf)
{
if (typeof Buffer._augment === 'function')
{
buf = Buffer._augment(buf);
if (!(buf instanceof Uint8Array))
{
throw Error('Assertion error, buf should be an Uint8Array');
}
}
else
{
buf = new Buffer(buf);
}
return buf;
}
function bufferToUint8Array(buf)
{
buf = new Uint8Array(buf);
if (typeof Buffer._augment === 'function')
{
buf = Buffer._augment(buf);
// buf is now both an Uint8Array and an Buffer
}
if (!(buf instanceof Uint8Array)) // this is the check ejson uses
{
// this is the check ejson uses
throw Error('Assertion error, buf should be an Uint8Array');
}
return buf;
}
ReadableBlobStream.prototype.read = function()
{
var buf = ReadableBlobStream.super_.prototype.read.apply(this, arguments);
// make sure it is a Uint8Array in case browserify's Buffer
// stops using Uint8Array
if (Buffer.isBuffer(buf) && !(buf instanceof Uint8Array))
{
buf = bufferToUint8Array(buf);
}
return buf;
};
ReadableBlobStream.prototype._read = function(chunkSize)
{
var size = this._blob.size;
var start, end;
start = this._nextByteStart;
end = Math.min(start + chunkSize, size); // exclusive
this._nextByteStart = end;
if (start >= this._blob.size)
{
return void this.push(null);
}
var chunk = this._blob.slice(start, end);
var reader = new FileReader();
reader.onload = function()
{
// reader.result is an ArrayBuffer
var buf = new Uint8Array(reader.result);
buf = uint8ArrayToBuffer(buf);
this.push(buf);
}.bind(this);
reader.onerror = function()
{
this.emit('error', reader.error);
}.bind(this);
reader.readAsArrayBuffer(chunk);
};
;