diff --git a/Module/PSMinIO/bin/PSMinIO.dll b/Module/PSMinIO/bin/PSMinIO.dll
index 9162723..22cdca6 100644
Binary files a/Module/PSMinIO/bin/PSMinIO.dll and b/Module/PSMinIO/bin/PSMinIO.dll differ
diff --git a/Module/PSMinIO/bin/PSMinIO.pdb b/Module/PSMinIO/bin/PSMinIO.pdb
index a458121..fcb7de1 100644
Binary files a/Module/PSMinIO/bin/PSMinIO.pdb and b/Module/PSMinIO/bin/PSMinIO.pdb differ
diff --git a/src/Utils/ZipArchiveBuilder.cs b/src/Utils/ZipArchiveBuilder.cs
index f61b97a..8e1b397 100644
--- a/src/Utils/ZipArchiveBuilder.cs
+++ b/src/Utils/ZipArchiveBuilder.cs
@@ -19,10 +19,10 @@ namespace PSMinIO.Utils
private bool _disposed = false;
// Performance optimization fields
- private const long FlushThreshold = 5 * 1024 * 1024; // 5MB (reduced for more frequent flushing)
+ private const long FlushThreshold = 1 * 1024 * 1024; // 1MB (very frequent flushing for real-time updates)
private long _bytesWrittenSinceFlush = 0;
private DateTime _lastFlush = DateTime.UtcNow;
- private const int FlushIntervalMs = 1000; // 1 second
+ private const int FlushIntervalMs = 500; // 500ms (very frequent time-based flushing)
// Cancellation support
private CancellationTokenSource? _cancellationTokenSource;
@@ -110,12 +110,12 @@ namespace PSMinIO.Utils
{
try
{
- _archive?.Dispose(); // This forces the zip to be finalized
+ // Force flush the output stream first
_outputStream?.Flush();
if (_outputStream is FileStream fileStream)
{
- fileStream.Flush(true); // Force OS flush
+ fileStream.Flush(true); // Force OS flush to disk
}
}
catch
@@ -124,6 +124,44 @@ namespace PSMinIO.Utils
}
}
+ ///
+ /// Aggressive flush that forces all buffers to disk
+ ///
+ private void AggressiveFlush()
+ {
+ try
+ {
+ // Try to flush the ZipArchive's internal buffers using reflection
+ var archiveType = _archive.GetType();
+ var streamField = archiveType.GetField("_archiveStream", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+ if (streamField?.GetValue(_archive) is Stream archiveStream)
+ {
+ archiveStream.Flush();
+ }
+
+ // Flush the output stream aggressively
+ _outputStream?.Flush();
+
+ if (_outputStream is FileStream fileStream)
+ {
+ fileStream.Flush(true); // Force OS-level flush
+ }
+
+ // Force garbage collection to ensure all buffers are released
+ GC.Collect(0, GCCollectionMode.Optimized);
+ }
+ catch
+ {
+ // Ignore flush errors - fallback to basic flush
+ try
+ {
+ _outputStream?.Flush();
+ if (_outputStream is FileStream fs) fs.Flush(true);
+ }
+ catch { }
+ }
+ }
+
///
/// Gets optimal buffer size based on file size
///
@@ -249,7 +287,7 @@ namespace PSMinIO.Utils
(now - _lastFlush).TotalMilliseconds > FlushIntervalMs)
{
entryStream.Flush();
- _outputStream.Flush(); // Also flush the underlying stream
+ AggressiveFlush(); // Force all data to disk immediately
_bytesWrittenSinceFlush = 0;
_lastFlush = now;
}
@@ -269,7 +307,7 @@ namespace PSMinIO.Utils
// Final flush for this file
entryStream.Flush();
- _outputStream.Flush(); // Force flush to disk
+ AggressiveFlush(); // Force all data to disk after each file
}
// Update metrics (access CompressedLength after the entry stream is closed)
diff --git a/src/Utils/ZipBuilder.cs b/src/Utils/ZipBuilder.cs
index 886c1bb..40ddcf0 100644
--- a/src/Utils/ZipBuilder.cs
+++ b/src/Utils/ZipBuilder.cs
@@ -204,12 +204,18 @@ namespace PSMinIO.Utils
/// Zip creation result
public ZipCreationResult CreateResult(string zipFilePath)
{
+ // Ensure the archive is completed before creating result
+ _zipBuilder.Complete();
+
+ var endTime = _zipBuilder.EndTime ?? DateTime.UtcNow;
+ var duration = _zipBuilder.Duration ?? TimeSpan.Zero;
+
return new ZipCreationResult
{
ZipFilePath = zipFilePath,
StartTime = _zipBuilder.StartTime,
- EndTime = _zipBuilder.EndTime ?? DateTime.UtcNow,
- Duration = _zipBuilder.Duration ?? TimeSpan.Zero,
+ EndTime = endTime,
+ Duration = duration,
FileCount = _zipBuilder.FileCount,
TotalUncompressedSize = _zipBuilder.TotalUncompressedSize,
TotalCompressedSize = _zipBuilder.TotalCompressedSize,