downloadFileBytes method
Download file content as bytes (no disk I/O — needed for Web platform).
Implementation
Future<Uint8List> downloadFileBytes(
String uuid, {
int maxConcurrentChunks = kDefaultDownloadConcurrency,
Function(int bytesDownloaded, int totalBytes)? onProgress,
}) async {
api.log('Downloading file bytes: $uuid');
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';
final fileSize = meta['size'] ?? 0;
final useConcurrency =
maxConcurrentChunks > 1 && chunks > kSequentialDownloadChunkThreshold;
int bytesDownloaded = 0;
if (!useConcurrency) {
final buffer = BytesBuilder();
for (var i = 0; i < chunks; i++) {
final decrypted = await _fetchChunk(host, d, uuid, i, keyBytes);
buffer.add(decrypted);
bytesDownloaded += decrypted.length;
if (onProgress != null) onProgress(bytesDownloaded, fileSize);
}
return buffer.toBytes();
}
// Fetch N chunks concurrently into ordered slots, then assemble in index
// order. The whole file is held in memory regardless (this API returns the
// full bytes); concurrency only overlaps the network fetches.
final slots = List<Uint8List?>.filled(chunks, null);
final sem = ChunkSemaphore(maxConcurrentChunks);
final inflight = <Future<void>>[];
Object? firstError;
for (var i = 0; i < chunks; i++) {
if (firstError != null) break;
await sem.acquire();
if (firstError != null) {
sem.release();
break;
}
final idx = i;
inflight.add(() async {
try {
final decrypted = await _fetchChunk(host, d, uuid, idx, keyBytes);
slots[idx] = decrypted;
bytesDownloaded += decrypted.length;
if (onProgress != null) onProgress(bytesDownloaded, fileSize);
} catch (e) {
firstError ??= e;
} finally {
sem.release();
}
}());
}
await Future.wait(inflight);
if (firstError != null) throw firstError!;
final buffer = BytesBuilder();
for (var i = 0; i < chunks; i++) {
buffer.add(slots[i]!);
}
return buffer.toBytes();
}