|
@@ -1,29 +1,24 @@
|
|
|
import 'dart:typed_data';
|
|
|
-
|
|
|
import 'package:dio/dio.dart';
|
|
|
-import 'package:flutter/foundation.dart';
|
|
|
|
|
|
//Raised when data is not ready.
|
|
|
class NotReadyException implements Exception {}
|
|
|
|
|
|
//Raised when errro happened during the downloading.
|
|
|
class DownloadErrorException implements Exception {
|
|
|
- String _msg;
|
|
|
+ String _message;
|
|
|
|
|
|
- DownloadErrorException(this._msg);
|
|
|
+ String get message => _message;
|
|
|
|
|
|
- @override
|
|
|
- String toString() {
|
|
|
- return _msg;
|
|
|
- }
|
|
|
+ DownloadErrorException(this._message);
|
|
|
}
|
|
|
|
|
|
typedef DownloadCallback = void Function(double progress);
|
|
|
|
|
|
class VidUsDataHttpReader {
|
|
|
- late final List<int> _data = [];
|
|
|
+ late Uint8List _underlyingData = Uint8List(0);
|
|
|
+ late int _bufferSize = 0;
|
|
|
late int _index;
|
|
|
- late ByteBuffer _buffer;
|
|
|
late bool _error;
|
|
|
late String _errorMsg;
|
|
|
late String _url;
|
|
@@ -32,47 +27,59 @@ class VidUsDataHttpReader {
|
|
|
|
|
|
DownloadCallback? downloadCallback;
|
|
|
|
|
|
- VidUsDataHttpReader(String url, {this.downloadCallback, int chunkSize = 32768}) {
|
|
|
+ VidUsDataHttpReader(String url, {this.downloadCallback, int chunkSize = 65536, int connectTimeout = 30000, int receiveTimeout = 30000}) {
|
|
|
_chunkSize = chunkSize;
|
|
|
_url = url;
|
|
|
_error = false;
|
|
|
_errorMsg = '';
|
|
|
- _buffer = Uint8List.fromList(_data).buffer;
|
|
|
_index = 0;
|
|
|
_dio = Dio();
|
|
|
- //TODO let the user set the timeout.
|
|
|
- _dio.options.connectTimeout = 5000; //5S
|
|
|
- _dio.options.receiveTimeout = 3000;
|
|
|
+ _dio.options.connectTimeout = connectTimeout;
|
|
|
+ _dio.options.receiveTimeout = receiveTimeout;
|
|
|
_startDownload();
|
|
|
}
|
|
|
|
|
|
void _startDownload() async {
|
|
|
- //get file info
|
|
|
- var fileSize = await _getFileSize();
|
|
|
- if (!_error) {
|
|
|
- var last = fileSize % _chunkSize;
|
|
|
- var chunkCount = fileSize ~/ _chunkSize;
|
|
|
- for (var i = 0; i < chunkCount; i++) {
|
|
|
- var start = i * _chunkSize;
|
|
|
- var end = start + _chunkSize;
|
|
|
- await _downloadChunk(start, end);
|
|
|
- if (_error) {
|
|
|
- break;
|
|
|
- }
|
|
|
- if (downloadCallback != null) {
|
|
|
- var progress = _data.length / fileSize;
|
|
|
- downloadCallback!(progress);
|
|
|
- }
|
|
|
- }
|
|
|
- if (!_error && last > 0) {
|
|
|
- var start = chunkCount * _chunkSize;
|
|
|
- var end = start + last;
|
|
|
- await _downloadChunk(start, end);
|
|
|
- if (!_error && downloadCallback != null) {
|
|
|
- var progress = _data.length / fileSize;
|
|
|
- downloadCallback!(progress);
|
|
|
+ try {
|
|
|
+ //get file info
|
|
|
+ var fileSize = await _getFileSize();
|
|
|
+ if (!_error) {
|
|
|
+ _underlyingData = Uint8List(fileSize);
|
|
|
+ if (fileSize < _chunkSize) {
|
|
|
+ await _downloadChunk(0, fileSize -1);
|
|
|
+ if (!_error && downloadCallback != null) {
|
|
|
+ var progress = _bufferSize / fileSize;
|
|
|
+ downloadCallback!(progress);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ var last = fileSize % _chunkSize;
|
|
|
+ var chunkCount = fileSize ~/ _chunkSize;
|
|
|
+ for (var i = 0; i < chunkCount; i++) {
|
|
|
+ var start = i * _chunkSize;
|
|
|
+ var end = start + _chunkSize - 1;
|
|
|
+ await _downloadChunk(start, end);
|
|
|
+ if (_error) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (downloadCallback != null) {
|
|
|
+ var progress = _bufferSize / fileSize;
|
|
|
+ downloadCallback!(progress);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!_error && last > 0) {
|
|
|
+ var start = chunkCount * _chunkSize;
|
|
|
+ var end = start + last - 1;
|
|
|
+ await _downloadChunk(start, end);
|
|
|
+ if (!_error && downloadCallback != null) {
|
|
|
+ var progress = _bufferSize / fileSize;
|
|
|
+ downloadCallback!(progress);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+ } catch (ex) {
|
|
|
+ _error = true;
|
|
|
+ _errorMsg = ex.toString();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -104,8 +111,8 @@ class VidUsDataHttpReader {
|
|
|
_errorMsg = 'Download chunk error.';
|
|
|
} else {
|
|
|
//Update the buffer.
|
|
|
- _data.addAll(downloadedData);
|
|
|
- _buffer = Uint8List.fromList(_data).buffer;
|
|
|
+ _underlyingData.setAll(_bufferSize, downloadedData);
|
|
|
+ _bufferSize += downloadedData.length;
|
|
|
}
|
|
|
} else {
|
|
|
_error = true;
|
|
@@ -114,7 +121,7 @@ class VidUsDataHttpReader {
|
|
|
}
|
|
|
|
|
|
//Close the reader and its http connection.
|
|
|
- void close(){
|
|
|
+ void close() {
|
|
|
_dio.close(force: true);
|
|
|
}
|
|
|
|
|
@@ -124,17 +131,17 @@ class VidUsDataHttpReader {
|
|
|
throw DownloadErrorException(_errorMsg);
|
|
|
}
|
|
|
if (index == -1) {
|
|
|
- if ((_buffer.lengthInBytes - _index) < 4) {
|
|
|
+ if ((_bufferSize - _index) < 4) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
- var intData = _buffer.asByteData(_index, 4);
|
|
|
+ var intData = _underlyingData.buffer.asByteData(_index, 4);
|
|
|
_index += 4;
|
|
|
return intData.getInt32(0, Endian.little);
|
|
|
} else {
|
|
|
- if ((_buffer.lengthInBytes - index) < 4) {
|
|
|
+ if ((_bufferSize - index) < 4) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
- var intData = _buffer.asByteData(index, 4);
|
|
|
+ var intData = _underlyingData.buffer.asByteData(index, 4);
|
|
|
_index = index + 4;
|
|
|
return intData.getInt32(0, Endian.little);
|
|
|
}
|
|
@@ -148,16 +155,16 @@ class VidUsDataHttpReader {
|
|
|
int dataLength;
|
|
|
if (index == -1) {
|
|
|
dataLength = readInt();
|
|
|
- if ((_buffer.lengthInBytes - _index) < dataLength) {
|
|
|
+ if ((_bufferSize - _index) < dataLength) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
} else {
|
|
|
dataLength = readInt(index);
|
|
|
- if ((_buffer.lengthInBytes - index) < dataLength) {
|
|
|
+ if ((_bufferSize - index) < dataLength) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
}
|
|
|
- var stringData = _buffer.asUint8List(_index, dataLength);
|
|
|
+ var stringData = _underlyingData.buffer.asUint8List(_index, dataLength);
|
|
|
_index += dataLength;
|
|
|
var unicodeStringData = Uint8List.fromList(stringData.toList()).buffer.asUint16List();
|
|
|
return String.fromCharCodes(unicodeStringData);
|
|
@@ -169,17 +176,17 @@ class VidUsDataHttpReader {
|
|
|
throw DownloadErrorException(_errorMsg);
|
|
|
}
|
|
|
if (index == -1) {
|
|
|
- if ((_buffer.lengthInBytes - _index) < 2) {
|
|
|
+ if ((_bufferSize - _index) < 2) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
- var intData = _buffer.asByteData(_index, 2);
|
|
|
+ var intData = _underlyingData.buffer.asByteData(_index, 2);
|
|
|
_index += 2;
|
|
|
return intData.getInt16(0, Endian.little);
|
|
|
} else {
|
|
|
- if ((_buffer.lengthInBytes - index) < 2) {
|
|
|
+ if ((_bufferSize - index) < 2) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
- var intData = _buffer.asByteData(index, 2);
|
|
|
+ var intData = _underlyingData.buffer.asByteData(index, 2);
|
|
|
_index = index + 2;
|
|
|
return intData.getInt16(0, Endian.little);
|
|
|
}
|
|
@@ -192,17 +199,17 @@ class VidUsDataHttpReader {
|
|
|
throw DownloadErrorException(_errorMsg);
|
|
|
}
|
|
|
if (index == -1) {
|
|
|
- if ((_buffer.lengthInBytes - _index) < 8) {
|
|
|
+ if ((_bufferSize - _index) < 8) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
- var intData = _buffer.asByteData(_index, 8);
|
|
|
+ var intData = _underlyingData.buffer.asByteData(_index, 8);
|
|
|
_index += 8;
|
|
|
return intData.getInt64(0, Endian.little);
|
|
|
} else {
|
|
|
- if ((_buffer.lengthInBytes - index) < 8) {
|
|
|
+ if ((_bufferSize - index) < 8) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
- var intData = _buffer.asByteData(index, 8);
|
|
|
+ var intData = _underlyingData.buffer.asByteData(index, 8);
|
|
|
_index = index + 8;
|
|
|
return intData.getInt64(0, Endian.little);
|
|
|
}
|
|
@@ -215,7 +222,7 @@ class VidUsDataHttpReader {
|
|
|
throw DownloadErrorException(_errorMsg);
|
|
|
}
|
|
|
if (index == -1) {
|
|
|
- if ((_buffer.lengthInBytes - _index) < 8) {
|
|
|
+ if ((_bufferSize - _index) < 8) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
int low = readInt();
|
|
@@ -224,7 +231,7 @@ class VidUsDataHttpReader {
|
|
|
value |= low;
|
|
|
return value;
|
|
|
} else {
|
|
|
- if ((_buffer.lengthInBytes - index) < 8) {
|
|
|
+ if ((_bufferSize - index) < 8) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
int low = readInt(index);
|
|
@@ -242,17 +249,17 @@ class VidUsDataHttpReader {
|
|
|
throw DownloadErrorException(_errorMsg);
|
|
|
}
|
|
|
if (index == -1) {
|
|
|
- if ((_buffer.lengthInBytes - _index) < 4) {
|
|
|
+ if ((_bufferSize - _index) < 4) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
- var floatData = _buffer.asByteData(_index, 4);
|
|
|
+ var floatData = _underlyingData.buffer.asByteData(_index, 4);
|
|
|
_index += 4;
|
|
|
return floatData.getFloat32(0, Endian.little);
|
|
|
} else {
|
|
|
- if ((_buffer.lengthInBytes - index) < 4) {
|
|
|
+ if ((_bufferSize - index) < 4) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
- var floatData = _buffer.asByteData(index, 4);
|
|
|
+ var floatData = _underlyingData.buffer.asByteData(index, 4);
|
|
|
_index = index + 4;
|
|
|
return floatData.getFloat32(0, Endian.little);
|
|
|
}
|
|
@@ -264,17 +271,17 @@ class VidUsDataHttpReader {
|
|
|
throw DownloadErrorException(_errorMsg);
|
|
|
}
|
|
|
if (index == -1) {
|
|
|
- if ((_buffer.lengthInBytes - _index) < 8) {
|
|
|
+ if ((_bufferSize - _index) < 8) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
- var floatData = _buffer.asByteData(_index, 8);
|
|
|
+ var floatData = _underlyingData.buffer.asByteData(_index, 8);
|
|
|
_index += 8;
|
|
|
return floatData.getFloat64(0, Endian.little);
|
|
|
} else {
|
|
|
- if ((_buffer.lengthInBytes - index) < 8) {
|
|
|
+ if ((_bufferSize - index) < 8) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
- var floatData = _buffer.asByteData(index, 8);
|
|
|
+ var floatData = _underlyingData.buffer.asByteData(index, 8);
|
|
|
_index = index + 8;
|
|
|
return floatData.getFloat64(0, Endian.little);
|
|
|
}
|
|
@@ -286,17 +293,17 @@ class VidUsDataHttpReader {
|
|
|
throw DownloadErrorException(_errorMsg);
|
|
|
}
|
|
|
if (index == -1) {
|
|
|
- if ((_buffer.lengthInBytes - _index) < 1) {
|
|
|
+ if ((_bufferSize - _index) < 1) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
- var boolData = _buffer.asByteData(_index, 1);
|
|
|
+ var boolData = _underlyingData.buffer.asByteData(_index, 1);
|
|
|
_index++;
|
|
|
return boolData.getInt8(0) == 1;
|
|
|
} else {
|
|
|
- if ((_buffer.lengthInBytes - index) < 1) {
|
|
|
+ if ((_bufferSize - index) < 1) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
- var boolData = _buffer.asByteData(index, 1);
|
|
|
+ var boolData = _underlyingData.buffer.asByteData(index, 1);
|
|
|
_index = index + 1;
|
|
|
return boolData.getInt8(0) == 1;
|
|
|
}
|
|
@@ -308,17 +315,17 @@ class VidUsDataHttpReader {
|
|
|
throw DownloadErrorException(_errorMsg);
|
|
|
}
|
|
|
if (index == -1) {
|
|
|
- if ((_buffer.lengthInBytes - _index) < 1) {
|
|
|
+ if ((_bufferSize - _index) < 1) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
- var byteData = _buffer.asByteData(_index, 1);
|
|
|
+ var byteData = _underlyingData.buffer.asByteData(_index, 1);
|
|
|
_index++;
|
|
|
return byteData.getInt8(0);
|
|
|
} else {
|
|
|
- if ((_buffer.lengthInBytes - index) < 1) {
|
|
|
+ if ((_bufferSize - index) < 1) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
- var byteData = _buffer.asByteData(index, 1);
|
|
|
+ var byteData = _underlyingData.buffer.asByteData(index, 1);
|
|
|
_index = index + 1;
|
|
|
return byteData.getInt8(0);
|
|
|
}
|
|
@@ -330,10 +337,10 @@ class VidUsDataHttpReader {
|
|
|
throw DownloadErrorException(_errorMsg);
|
|
|
}
|
|
|
var dataLength = readInt(index);
|
|
|
- if ((_buffer.lengthInBytes - _index) < dataLength) {
|
|
|
+ if ((_bufferSize - _index) < dataLength) {
|
|
|
throw NotReadyException();
|
|
|
}
|
|
|
- var bytes = _buffer.asUint8List(_index, dataLength);
|
|
|
+ var bytes = _underlyingData.buffer.asUint8List(_index, dataLength);
|
|
|
_index += dataLength;
|
|
|
return bytes;
|
|
|
}
|