diff --git a/src/Downloader.Test/DownloadIntegrationTest.cs b/src/Downloader.Test/DownloadIntegrationTest.cs index 500fee16..3888f17d 100644 --- a/src/Downloader.Test/DownloadIntegrationTest.cs +++ b/src/Downloader.Test/DownloadIntegrationTest.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Newtonsoft.Json; namespace Downloader.Test { @@ -36,7 +37,37 @@ public void Download1KbWithFilenameTest() Assert.IsNotNull(memoryStream); Assert.AreEqual(DownloadTestHelper.FileSize1Kb, downloader.Package.TotalFileSize); Assert.AreEqual(DownloadTestHelper.FileSize1Kb, memoryStream.Length); - Assert.IsTrue(DownloadTestHelper.AreEqual(DownloadTestHelper.File1Kb, memoryStream)); + Assert.IsTrue(DownloadTestHelper.File1Kb.AreEqual(memoryStream)); + } + + [TestMethod] + public void TestDownloadAndExecuteFileInDownloadCompletedEvent() + { + // arrange + byte[] downloadedBytes = null; + var downloadCompletedSuccessfully = false; + var downloader = new DownloadService(Config); + downloader.DownloadFileCompleted += (s, e) => { + if (e.Cancelled == false && e.Error == null) + { + // Execute the downloaded file within completed event + // Note: Execute within this event caused to an IOException: + // The process cannot access the file '...\Temp\tmp14D3.tmp' because it is being used by another process.) + + downloadCompletedSuccessfully = true; + downloadedBytes = File.ReadAllBytes(downloader.Package.FileName); + } + }; + + // act + downloader.DownloadFileTaskAsync(DownloadTestHelper.File1KbUrl, Path.GetTempFileName()).Wait(); + + // assert + Assert.IsTrue(downloadCompletedSuccessfully); + Assert.IsNotNull(downloadedBytes); + Assert.AreEqual(DownloadTestHelper.FileSize1Kb, downloader.Package.TotalFileSize); + Assert.AreEqual(DownloadTestHelper.FileSize1Kb, downloadedBytes.Length); + Assert.IsTrue(DownloadTestHelper.File1Kb.AreEqual(new MemoryStream(downloadedBytes))); } [TestMethod] @@ -53,7 +84,7 @@ public void Download16KbWithoutFilenameTest() Assert.IsTrue(File.Exists(downloader.Package.FileName)); Assert.IsTrue(downloader.Package.FileName.StartsWith(DownloadTestHelper.TempDirectory)); Assert.AreEqual(DownloadTestHelper.FileSize16Kb, downloader.Package.TotalFileSize); - Assert.IsTrue(DownloadTestHelper.AreEqual(DownloadTestHelper.File16Kb, File.OpenRead(downloader.Package.FileName))); + Assert.IsTrue(DownloadTestHelper.File16Kb.AreEqual(File.OpenRead(downloader.Package.FileName))); File.Delete(downloader.Package.FileName); } @@ -157,6 +188,45 @@ public void StopResumeDownloadFromLastPositionTest() Assert.AreEqual(DownloadTestHelper.FileSize16Kb, totalReceivedBytes); } + [TestMethod] + public void StopResumeDownloadOverFirstPackagePositionTest() + { + // arrange + var packageCheckPoint = new DownloadPackage() { Address = DownloadTestHelper.File16KbUrl }; + var stopThreshold = 4100; + var totalReceivedBytes = 0L; + var downloader = new DownloadService(Config); + + downloader.DownloadProgressChanged += (s, e) => { + totalReceivedBytes += e.ReceivedBytes.Length; + + if (e.ReceivedBytesSize > stopThreshold) + { + // Stopping after start of downloading + downloader.CancelAsync(); + stopThreshold *= 2; + + // check point of package for once time + packageCheckPoint.Chunks ??= downloader.Package.Chunks.Clone() as Chunk[]; + } + }; + + // act + downloader.DownloadFileTaskAsync(packageCheckPoint.Address).Wait(); + while (downloader.IsCancelled) + { + var firstCheckPointClone = new DownloadPackage() { + Address = packageCheckPoint.Address, Chunks = packageCheckPoint.Chunks.Clone() as Chunk[] + }; + // resume download from first stopped point. + downloader.DownloadFileTaskAsync(firstCheckPointClone).Wait(); + } + + // assert + Assert.AreEqual(DownloadTestHelper.FileSize16Kb, downloader.Package.TotalFileSize); + Assert.AreEqual(DownloadTestHelper.FileSize16Kb, totalReceivedBytes); + } + [TestMethod] public void TestTotalReceivedBytesWhenResumeDownload() { diff --git a/src/Downloader/DownloadService.cs b/src/Downloader/DownloadService.cs index 221fa269..5eeca575 100644 --- a/src/Downloader/DownloadService.cs +++ b/src/Downloader/DownloadService.cs @@ -182,21 +182,17 @@ private async Task StartDownload() private async Task StoreDownloadedFile(CancellationToken cancellationToken) { - try - { - _destinationStream = Package.FileName == null - ? new MemoryStream() - : FileHelper.CreateFile(Package.FileName); - await _chunkHub.MergeChunks(Package.Chunks, _destinationStream, cancellationToken).ConfigureAwait(false); - OnDownloadFileCompleted(new AsyncCompletedEventArgs(null, false, Package)); - } - finally + _destinationStream = Package.FileName == null + ? new MemoryStream() + : FileHelper.CreateFile(Package.FileName); + await _chunkHub.MergeChunks(Package.Chunks, _destinationStream, cancellationToken).ConfigureAwait(false); + + if (_destinationStream is FileStream) { - if (_destinationStream is FileStream) - { - _destinationStream?.Dispose(); - } + _destinationStream?.Dispose(); } + + OnDownloadFileCompleted(new AsyncCompletedEventArgs(null, false, Package)); } private void Validate() diff --git a/src/Downloader/Downloader.csproj b/src/Downloader/Downloader.csproj index 396cf810..d2317123 100644 --- a/src/Downloader/Downloader.csproj +++ b/src/Downloader/Downloader.csproj @@ -3,7 +3,7 @@ netstandard2.0;net5.0;net45 9.0 - 2.2.7 + 2.2.8 Downloader Behzad Khosravifar bezzad @@ -21,8 +21,8 @@ LICENSE downloader.png git - 2.2.7 - 2.2.7 + 2.2.8 + 2.2.8 diff --git a/src/Downloader/FileHelper.cs b/src/Downloader/FileHelper.cs index 9a948c18..430bc2d3 100644 --- a/src/Downloader/FileHelper.cs +++ b/src/Downloader/FileHelper.cs @@ -18,7 +18,7 @@ public static Stream CreateFile(string filename) Directory.CreateDirectory(directory); } - return new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete); + return new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete); } public static string GetTempFile() {