writeToFile method
Implementation
Future<void> writeToFile(
String path, {
Uint8List? coverImage,
void Function(String name, double progress)? onProgress,
}) async {
final file = File(path);
final sink = file.openWrite();
// --- MAGIC + VERSION + FLAGS ---
sink.add(utf8.encode(mime)); // magic
sink.add([version]);
int flags = 0;
if (coverImage != null) flags |= 1 << 0;
sink.add([flags]);
// --- Optional PNG Cover ---
if (coverImage != null) {
final coverSize = ByteData(4)..setUint32(0, coverImage.length);
sink.add(coverSize.buffer.asUint8List());
sink.add(coverImage);
}
// --- Config JSON ---
final configJson = utf8.encode(jsonEncode(config));
final configSize = ByteData(4)..setUint32(0, configJson.length);
sink.add(configSize.buffer.asUint8List());
sink.add(configJson);
// --- File Index Section (names, offsets, lengths) ---
// final indexStart = await file.length(); // save index start position
// final fileCount = files.length;
// placeholder for file index
final fileIndex = BytesBuilder();
int currentOffset = 0;
for (final f in files) {
final nameBytes = utf8.encode(f.name);
final nameLen = ByteData(2)..setUint16(0, nameBytes.length);
final offsetBytes = ByteData(8)..setInt64(0, currentOffset);
final lengthBytes = ByteData(8)..setInt64(0, f.data.length);
fileIndex.add(nameLen.buffer.asUint8List());
fileIndex.add(nameBytes);
fileIndex.add(offsetBytes.buffer.asUint8List());
fileIndex.add(lengthBytes.buffer.asUint8List());
currentOffset += f.data.length;
}
final indexBytes = fileIndex.toBytes();
final indexSize = ByteData(4)..setUint32(0, indexBytes.length);
sink.add(indexSize.buffer.asUint8List());
sink.add(indexBytes);
// --- Write Actual File Data ---
int writtenSize = 0;
final totalSize = files.fold<int>(0, (sum, f) => sum + f.data.length);
for (final f in files) {
final data = f.data;
const chunkSize = 1024 * 1024;
int offset = 0;
while (offset < data.length) {
final end = (offset + chunkSize).clamp(0, data.length);
sink.add(data.sublist(offset, end));
writtenSize += (end - offset);
offset = end;
if (onProgress != null) {
onProgress(f.name, writtenSize / totalSize);
}
}
}
await sink.flush();
await sink.close();
}