|
|
@@ -631,20 +631,35 @@ host.BrowserHost.BrowserFileContext = class {
|
|
|
}
|
|
|
return new Promise((resolve, reject) => {
|
|
|
const reader = new FileReader();
|
|
|
+ const size = 1024 * 1024 * 1024;
|
|
|
+ let position = 0;
|
|
|
+ const chunks = [];
|
|
|
reader.onload = (e) => {
|
|
|
if (encoding) {
|
|
|
resolve(e.target.result);
|
|
|
} else {
|
|
|
- const base = require('./base');
|
|
|
const buffer = new Uint8Array(e.target.result);
|
|
|
- const stream = new base.BinaryStream(buffer);
|
|
|
- resolve(stream);
|
|
|
+ if (position === 0 && buffer.length === blob.size) {
|
|
|
+ const base = require('./base');
|
|
|
+ const stream = new base.BinaryStream(buffer);
|
|
|
+ resolve(stream);
|
|
|
+ } else {
|
|
|
+ chunks.push(buffer);
|
|
|
+ position += buffer.length;
|
|
|
+ if (position < blob.size) {
|
|
|
+ const slice = blob.slice(position, Math.min(position + size, blob.size));
|
|
|
+ reader.readAsArrayBuffer(slice);
|
|
|
+ } else {
|
|
|
+ const stream = new host.BrowserHost.FileStream(chunks, size, 0, position);
|
|
|
+ resolve(stream);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
};
|
|
|
- reader.onerror = (e) => {
|
|
|
- e = e || this.window.event;
|
|
|
+ reader.onerror = (event) => {
|
|
|
+ event = event || this._host.window.event;
|
|
|
let message = '';
|
|
|
- const error = e.target.error;
|
|
|
+ const error = event.target.error;
|
|
|
switch (error.code) {
|
|
|
case error.NOT_FOUND_ERR:
|
|
|
message = "File not found '" + file + "'.";
|
|
|
@@ -664,7 +679,8 @@ host.BrowserHost.BrowserFileContext = class {
|
|
|
if (encoding === 'utf-8') {
|
|
|
reader.readAsText(blob, encoding);
|
|
|
} else {
|
|
|
- reader.readAsArrayBuffer(blob);
|
|
|
+ const slice = blob.slice(position, Math.min(position + size, blob.size));
|
|
|
+ reader.readAsArrayBuffer(slice);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
@@ -682,6 +698,99 @@ host.BrowserHost.BrowserFileContext = class {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+host.BrowserHost.FileStream = class {
|
|
|
+
|
|
|
+ constructor(chunks, size, start, length) {
|
|
|
+ this._chunks = chunks;
|
|
|
+ this._size = size;
|
|
|
+ this._start = start;
|
|
|
+ this._length = length;
|
|
|
+ this._position = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ get position() {
|
|
|
+ return this._position;
|
|
|
+ }
|
|
|
+
|
|
|
+ get length() {
|
|
|
+ return this._length;
|
|
|
+ }
|
|
|
+
|
|
|
+ stream(length) {
|
|
|
+ const file = new host.BrowserHost.FileStream(this._chunks, this._size, this._position, length);
|
|
|
+ this.skip(length);
|
|
|
+ return file;
|
|
|
+ }
|
|
|
+
|
|
|
+ seek(position) {
|
|
|
+ this._position = position >= 0 ? position : this._length + position;
|
|
|
+ }
|
|
|
+
|
|
|
+ skip(offset) {
|
|
|
+ this._position += offset;
|
|
|
+ if (this._position > this._length) {
|
|
|
+ throw new Error('Expected ' + (this._position - this._length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ peek(length) {
|
|
|
+ length = length !== undefined ? length : this._length - this._position;
|
|
|
+ if (length < 0x10000000) {
|
|
|
+ const position = this._fill(length);
|
|
|
+ this._position -= length;
|
|
|
+ return this._buffer.subarray(position, position + length);
|
|
|
+ }
|
|
|
+ const position = this._position;
|
|
|
+ this.skip(length);
|
|
|
+ this.seek(position);
|
|
|
+ const buffer = new Uint8Array(length);
|
|
|
+ this._read(buffer, position);
|
|
|
+ return buffer;
|
|
|
+ }
|
|
|
+
|
|
|
+ read(length) {
|
|
|
+ length = length !== undefined ? length : this._length - this._position;
|
|
|
+ if (length < 0x10000000) {
|
|
|
+ const position = this._fill(length);
|
|
|
+ return this._buffer.subarray(position, position + length);
|
|
|
+ }
|
|
|
+ const position = this._position;
|
|
|
+ this.skip(length);
|
|
|
+ const buffer = new Uint8Array(length);
|
|
|
+ this._read(buffer, position);
|
|
|
+ return buffer;
|
|
|
+ }
|
|
|
+
|
|
|
+ byte() {
|
|
|
+ const position = this._fill(1);
|
|
|
+ return this._buffer[position];
|
|
|
+ }
|
|
|
+
|
|
|
+ _fill(length) {
|
|
|
+ if (this._position + length > this._length) {
|
|
|
+ throw new Error('Expected ' + (this._position + length - this._length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
|
|
|
+ }
|
|
|
+ if (!this._buffer || this._position < this._offset || this._position + length > this._offset + this._buffer.length) {
|
|
|
+ this._offset = this._position;
|
|
|
+ this._buffer = new Uint8Array(Math.min(0x10000000, this._size, this._length - this._offset));
|
|
|
+ this._read(this._buffer, this._offset);
|
|
|
+ }
|
|
|
+ const position = this._position;
|
|
|
+ this._position += length;
|
|
|
+ return position - this._offset;
|
|
|
+ }
|
|
|
+
|
|
|
+ _read(buffer, offset) {
|
|
|
+ const index = Math.floor(offset / this._size);
|
|
|
+ offset = offset - (index * this._size);
|
|
|
+ const length = Math.min(this._chunks[index].length - offset, buffer.length);
|
|
|
+ buffer.set(this._chunks[index].subarray(offset, offset + length), 0);
|
|
|
+ if (length !== buffer.length) {
|
|
|
+ buffer.set(this._chunks[index + 1].subarray(0, buffer.length - length), length);
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
host.BrowserHost.Context = class {
|
|
|
|
|
|
constructor(host, url, identifier, stream) {
|