diff --git a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs index f4f8cb6b..878ad797 100644 --- a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs +++ b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using SharpCompress.Common; using SharpCompress.IO; using SharpCompress.Readers; @@ -7,7 +8,7 @@ namespace SharpCompress.Archives { public static class IArchiveEntryExtensions { - public static void WriteTo(this IArchiveEntry archiveEntry, Stream streamToWriteTo) + public static void WriteTo(this IArchiveEntry archiveEntry, Stream streamToWriteTo, Action partTransferredAction = null) { if (archiveEntry.Archive.Type == ArchiveType.Rar && archiveEntry.Archive.IsSolid) { @@ -32,7 +33,7 @@ namespace SharpCompress.Archives { using (Stream s = new ListeningStream(streamListener, entryStream)) { - s.TransferTo(streamToWriteTo); + s.TransferTo(streamToWriteTo, partTransferredAction); } } streamListener.FireEntryExtractionEnd(archiveEntry); diff --git a/src/SharpCompress/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs index 380e8df5..a055c17f 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -167,7 +167,7 @@ namespace SharpCompress.Readers } } - public void WriteEntryTo(Stream writableStream) + public void WriteEntryTo(Stream writableStream, Action partTransferredAction = null) { if (wroteCurrentEntry) { @@ -175,22 +175,21 @@ namespace SharpCompress.Readers } if ((writableStream == null) || (!writableStream.CanWrite)) { - throw new ArgumentNullException( - "A writable Stream was required. Use Cancel if that was intended."); + throw new ArgumentNullException("A writable Stream was required. Use Cancel if that was intended."); } var streamListener = this as IReaderExtractionListener; streamListener.FireEntryExtractionBegin(Entry); - Write(writableStream); + Write(writableStream, partTransferredAction); streamListener.FireEntryExtractionEnd(Entry); wroteCurrentEntry = true; } - internal void Write(Stream writeStream) + internal void Write(Stream writeStream, Action partTransferredAction = null) { using (Stream s = OpenEntryStream()) { - s.TransferTo(writeStream); + s.TransferTo(writeStream, partTransferredAction); } } diff --git a/src/SharpCompress/Readers/IReader.cs b/src/SharpCompress/Readers/IReader.cs index 0df03177..6b1a7818 100644 --- a/src/SharpCompress/Readers/IReader.cs +++ b/src/SharpCompress/Readers/IReader.cs @@ -20,7 +20,8 @@ namespace SharpCompress.Readers /// Decompresses the current entry to the stream. This cannot be called twice for the current entry. /// /// - void WriteEntryTo(Stream writableStream); + /// + void WriteEntryTo(Stream writableStream, Action partTransferredAction = null); bool Cancelled { get; } void Cancel(); diff --git a/src/SharpCompress/Readers/IReaderExtensions.cs b/src/SharpCompress/Readers/IReaderExtensions.cs index 4100a607..2fdeb1d9 100644 --- a/src/SharpCompress/Readers/IReaderExtensions.cs +++ b/src/SharpCompress/Readers/IReaderExtensions.cs @@ -1,4 +1,5 @@ #if !NO_FILE +using System; using System.IO; using SharpCompress.Common; #endif @@ -39,8 +40,12 @@ namespace SharpCompress.Readers /// /// Extract to specific directory, retaining filename /// - public static void WriteEntryToDirectory(this IReader reader, string destinationDirectory, - ExtractionOptions options = null) + public static void WriteEntryToDirectory( + this IReader reader, + string destinationDirectory, + ExtractionOptions options = null, + Action partTransferredAction = null + ) { string destinationFileName = string.Empty; string file = Path.GetFileName(reader.Entry.Key); @@ -66,7 +71,7 @@ namespace SharpCompress.Readers if (!reader.Entry.IsDirectory) { - reader.WriteEntryToFile(destinationFileName, options); + reader.WriteEntryToFile(destinationFileName, options, partTransferredAction); } else if (options.ExtractFullPath && !Directory.Exists(destinationFileName)) { @@ -77,8 +82,12 @@ namespace SharpCompress.Readers /// /// Extract to specific file /// - public static void WriteEntryToFile(this IReader reader, string destinationFileName, - ExtractionOptions options = null) + public static void WriteEntryToFile( + this IReader reader, + string destinationFileName, + ExtractionOptions options = null, + Action partTransferredAction = null + ) { FileMode fm = FileMode.Create; options = options ?? new ExtractionOptions() @@ -92,7 +101,7 @@ namespace SharpCompress.Readers } using (FileStream fs = File.Open(destinationFileName, fm)) { - reader.WriteEntryTo(fs); + reader.WriteEntryTo(fs, partTransferredAction); //using (Stream s = reader.OpenEntryStream()) //{ // s.TransferTo(fs); diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index 451075f3..253e0e9d 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -229,15 +229,18 @@ namespace SharpCompress return DosDateToDateTime((UInt32)iTime); } - public static long TransferTo(this Stream source, Stream destination) + public static long TransferTo(this Stream source, Stream destination, Action partTransferredAction = null) { byte[] array = new byte[81920]; int count; + var iterations = 0; long total = 0; while ((count = source.Read(array, 0, array.Length)) != 0) { total += count; destination.Write(array, 0, count); + iterations++; + partTransferredAction?.Invoke(total, iterations); } return total; } diff --git a/src/SharpCompress/Writers/AbstractWriter.cs b/src/SharpCompress/Writers/AbstractWriter.cs index dde6892a..79f880b9 100644 --- a/src/SharpCompress/Writers/AbstractWriter.cs +++ b/src/SharpCompress/Writers/AbstractWriter.cs @@ -24,7 +24,7 @@ namespace SharpCompress.Writers public ArchiveType WriterType { get; } - public abstract void Write(string filename, Stream source, DateTime? modificationTime); + public abstract void Write(string filename, Stream source, DateTime? modificationTime, Action partTransferredAction = null); protected virtual void Dispose(bool isDisposing) { diff --git a/src/SharpCompress/Writers/GZip/GZipWriter.cs b/src/SharpCompress/Writers/GZip/GZipWriter.cs index d9ef3562..48b88a29 100644 --- a/src/SharpCompress/Writers/GZip/GZipWriter.cs +++ b/src/SharpCompress/Writers/GZip/GZipWriter.cs @@ -26,7 +26,7 @@ namespace SharpCompress.Writers.GZip base.Dispose(isDisposing); } - public override void Write(string filename, Stream source, DateTime? modificationTime) + public override void Write(string filename, Stream source, DateTime? modificationTime, Action partTransferredAction = null) { if (wroteToStream) { @@ -35,7 +35,7 @@ namespace SharpCompress.Writers.GZip GZipStream stream = OutputStream as GZipStream; stream.FileName = filename; stream.LastModified = modificationTime; - source.TransferTo(stream); + source.TransferTo(stream, partTransferredAction); wroteToStream = true; } } diff --git a/src/SharpCompress/Writers/IWriter.cs b/src/SharpCompress/Writers/IWriter.cs index a15225bf..d55e8b74 100644 --- a/src/SharpCompress/Writers/IWriter.cs +++ b/src/SharpCompress/Writers/IWriter.cs @@ -7,6 +7,6 @@ namespace SharpCompress.Writers public interface IWriter : IDisposable { ArchiveType WriterType { get; } - void Write(string filename, Stream source, DateTime? modificationTime); + void Write(string filename, Stream source, DateTime? modificationTime, Action partTransferredAction = null); } } \ No newline at end of file diff --git a/src/SharpCompress/Writers/Tar/TarWriter.cs b/src/SharpCompress/Writers/Tar/TarWriter.cs index 0dbdb0a2..552b0c93 100644 --- a/src/SharpCompress/Writers/Tar/TarWriter.cs +++ b/src/SharpCompress/Writers/Tar/TarWriter.cs @@ -39,9 +39,9 @@ namespace SharpCompress.Writers.Tar InitalizeStream(destination, !options.LeaveStreamOpen); } - public override void Write(string filename, Stream source, DateTime? modificationTime) + public override void Write(string filename, Stream source, DateTime? modificationTime, Action partTransferredAction = null) { - Write(filename, source, modificationTime, null); + Write(filename, source, modificationTime, null, partTransferredAction); } private string NormalizeFilename(string filename) @@ -57,7 +57,7 @@ namespace SharpCompress.Writers.Tar return filename.Trim('/'); } - public void Write(string filename, Stream source, DateTime? modificationTime, long? size) + public void Write(string filename, Stream source, DateTime? modificationTime, long? size, Action partTransferredAction = null) { if (!source.CanSeek && size == null) { @@ -71,7 +71,7 @@ namespace SharpCompress.Writers.Tar header.Name = NormalizeFilename(filename); header.Size = realSize; header.Write(OutputStream); - size = source.TransferTo(OutputStream); + size = source.TransferTo(OutputStream, partTransferredAction); PadTo512(size.Value, false); } diff --git a/src/SharpCompress/Writers/Zip/ZipWriter.cs b/src/SharpCompress/Writers/Zip/ZipWriter.cs index e1a001b5..96efa0b6 100644 --- a/src/SharpCompress/Writers/Zip/ZipWriter.cs +++ b/src/SharpCompress/Writers/Zip/ZipWriter.cs @@ -90,19 +90,19 @@ namespace SharpCompress.Writers.Zip } } - public override void Write(string entryPath, Stream source, DateTime? modificationTime) + public override void Write(string entryPath, Stream source, DateTime? modificationTime, Action partTransferredAction = null) { Write(entryPath, source, new ZipWriterEntryOptions() { ModificationDateTime = modificationTime - }); + }, partTransferredAction); } - public void Write(string entryPath, Stream source, ZipWriterEntryOptions zipWriterEntryOptions) + public void Write(string entryPath, Stream source, ZipWriterEntryOptions zipWriterEntryOptions, Action partTransferredAction = null) { using (Stream output = WriteToStream(entryPath, zipWriterEntryOptions)) { - source.TransferTo(output); + source.TransferTo(output, partTransferredAction); } }