/// <summary> /// Check whether the destination file exists. If not, create a file with the same /// size as the file to be downloaded. /// </summary> void CheckFileOrCreateFile() { DownloaderHelper.CheckFileOrCreateFile(this, fileLocker); }
/// <summary> /// Download the data using HttpWebRequest. It will read a buffer of bytes from the /// response stream, and store the buffer to a MemoryStream cache first. /// If the cache is full, or the download is paused, canceled or completed, write /// the data in cache to local file. /// </summary> void DownloadInternal(object obj) { if (this.Status != DownloadStatus.Waiting) { return; } HttpWebRequest webRequest = null; HttpWebResponse webResponse = null; Stream responseStream = null; MemoryStream downloadCache = null; this.lastStartTime = DateTime.Now; try { if (!HasChecked) { string filename = string.Empty; CheckUrlAndFile(out filename); } this.EnsurePropertyValid(); // Set the status. this.Status = DownloadStatus.Downloading; // Create a request to the file to be downloaded. webRequest = DownloaderHelper.InitializeHttpWebRequest(this); // Specify the block to download. if (EndPoint != int.MaxValue) { webRequest.AddRange(StartPoint + DownloadedSize, EndPoint); } else { webRequest.AddRange(StartPoint + DownloadedSize); } // Retrieve the response from the server and get the response stream. webResponse = (HttpWebResponse)webRequest.GetResponse(); responseStream = webResponse.GetResponseStream(); // Cache data in memory. downloadCache = new MemoryStream(this.MaxCacheSize); byte[] downloadBuffer = new byte[this.BufferSize]; int bytesSize = 0; CachedSize = 0; int receivedBufferCount = 0; // Download the file until the download is paused, canceled or completed. while (true) { // Read a buffer of data from the stream. bytesSize = responseStream.Read(downloadBuffer, 0, downloadBuffer.Length); // If the cache is full, or the download is paused, canceled or // completed, write the data in cache to local file. if (this.Status != DownloadStatus.Downloading || bytesSize == 0 || this.MaxCacheSize < CachedSize + bytesSize) { try { // Write the data in cache to local file. WriteCacheToFile(downloadCache, CachedSize); this.DownloadedSize += CachedSize; // Stop downloading the file if the download is paused, // canceled or completed. if (this.Status != DownloadStatus.Downloading || bytesSize == 0) { break; } // Reset cache. downloadCache.Seek(0, SeekOrigin.Begin); CachedSize = 0; } catch (Exception ex) { // Fire the DownloadCompleted event with the error. this.OnDownloadCompleted( new DownloadCompletedEventArgs( null, this.DownloadedSize, this.TotalSize, this.TotalUsedTime, ex)); return; } } // Write the data from the buffer to the cache in memory. downloadCache.Write(downloadBuffer, 0, bytesSize); CachedSize += bytesSize; receivedBufferCount++; // Fire the DownloadProgressChanged event. if (receivedBufferCount == this.BufferCountPerNotification) { InternalDownloadProgressChanged(CachedSize); receivedBufferCount = 0; } } // Update the used time when the current doanload is stopped. usedTime = usedTime.Add(DateTime.Now - lastStartTime); // Update the status of the client. Above loop will be stopped when the // status of the client is pausing, canceling or completed. if (this.Status == DownloadStatus.Pausing) { this.Status = DownloadStatus.Paused; } else if (this.Status == DownloadStatus.Canceling) { this.Status = DownloadStatus.Canceled; } else { this.Status = DownloadStatus.Completed; return; } } catch (Exception ex) { // Fire the DownloadCompleted event with the error. this.OnDownloadCompleted( new DownloadCompletedEventArgs( null, this.DownloadedSize, this.TotalSize, this.TotalUsedTime, ex)); return; } finally { // When the above code has ended, close the streams. if (responseStream != null) { responseStream.Close(); } if (webResponse != null) { webResponse.Close(); } if (downloadCache != null) { downloadCache.Close(); } } }
/// <summary> /// Check the Uri to find its size, and whether it supports "Pause". /// </summary> public void CheckUrl(out string fileName) { fileName = DownloaderHelper.CheckUrl(this); }