downloadFileRange method
Download file with range support.
Implementation
Future<Uint8List> downloadFileRange(
String uuid, {
int? rangeStart,
int? rangeEnd,
}) async {
api.log('Downloading file range: $uuid ($rangeStart-$rangeEnd)');
final info = await api.post('/v3/file', {'uuid': uuid});
final d = info['data'];
final metaStr = await crypto.tryDecrypt(d['metadata'], masterKeys);
final meta = json.decode(metaStr);
final keyBytes = crypto.decodeUniversalKey(meta['key']);
final chunks = int.parse(d['chunks'].toString());
final host = 'https://egest.filen.io';
const chunkSize = 1048576;
final startChunk = rangeStart != null ? rangeStart ~/ chunkSize : 0;
final endChunk = rangeEnd != null ? rangeEnd ~/ chunkSize : chunks - 1;
final buffer = BytesBuilder();
for (var i = startChunk; i <= endChunk && i < chunks; i++) {
final r = await api.client
.get(Uri.parse('$host/${d['region']}/${d['bucket']}/$uuid/$i'));
if (r.statusCode != 200) {
throw Exception('Chunk download failed: ${r.statusCode}');
}
var chunkBytes = await crypto.decryptData(r.bodyBytes, keyBytes);
// Trim the tail of the last chunk, then the head of the first chunk.
// Trimming end-before-start keeps both offsets relative to the chunk
// start — required when the whole range lies within a single chunk
// (start == end), where the previous if/else only trimmed the head.
if (i == endChunk && rangeEnd != null) {
final endOffset = rangeEnd % chunkSize + 1;
if (endOffset < chunkBytes.length) {
chunkBytes = chunkBytes.sublist(0, endOffset);
}
}
if (i == startChunk && rangeStart != null) {
chunkBytes = chunkBytes.sublist(rangeStart % chunkSize);
}
buffer.add(chunkBytes);
}
return buffer.toBytes();
}