-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathHttpClientDownloadWithProgress.cs
More file actions
85 lines (68 loc) · 2.6 KB
/
Copy pathHttpClientDownloadWithProgress.cs
File metadata and controls
85 lines (68 loc) · 2.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
public class HttpClientDownloadWithProgress : IDisposable
{
readonly string _downloadUrl;
readonly string _destinationFilePath;
HttpClient? httpClient;
DateTime _startedAt = DateTime.Now;
public delegate void ProgressChangedHandler(long? totalFileSize, long totalBytesDownloaded, double? progressPercentage, double rate);
public event ProgressChangedHandler? ProgressChanged;
public HttpClientDownloadWithProgress(string downloadUrl, string destinationFilePath)
{
_downloadUrl = downloadUrl;
_destinationFilePath = destinationFilePath;
}
public async Task StartDownload()
{
httpClient = new HttpClient { Timeout = TimeSpan.FromDays(1) };
using (var response = await httpClient.GetAsync(_downloadUrl, HttpCompletionOption.ResponseHeadersRead))
await DownloadFileFromHttpResponseMessage(response);
}
async Task DownloadFileFromHttpResponseMessage(HttpResponseMessage response)
{
response.EnsureSuccessStatusCode();
var totalBytes = response.Content.Headers.ContentLength;
using (var contentStream = await response.Content.ReadAsStreamAsync())
await ProcessContentStream(totalBytes, contentStream);
}
async Task ProcessContentStream(long? totalDownloadSize, Stream contentStream)
{
var totalBytesRead = 0L;
var readCount = 0L;
var buffer = new byte[8192];
var isMoreToRead = true;
using (var fileStream = new FileStream(_destinationFilePath, FileMode.Create, FileAccess.Write, FileShare.None, 8192, true))
{
do
{
var bytesRead = await contentStream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0)
{
isMoreToRead = false;
TriggerProgressChanged(totalDownloadSize, totalBytesRead);
continue;
}
await fileStream.WriteAsync(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
readCount += 1;
if (readCount % 100 == 0)
TriggerProgressChanged(totalDownloadSize, totalBytesRead);
}
while (isMoreToRead);
}
}
void TriggerProgressChanged(long? totalDownloadSize, long totalBytesRead)
{
var elapsed = (DateTime.Now - _startedAt) / 1000;
var rate = Math.Round((totalBytesRead / elapsed.TotalMilliseconds)/1024/1024,1);
if (ProgressChanged == null)
return;
double? progressPercentage = null;
if (totalDownloadSize.HasValue)
progressPercentage = Math.Round((double)totalBytesRead / totalDownloadSize.Value * 100, 0);
ProgressChanged(totalDownloadSize/1024/1024, totalBytesRead/1024/1024, progressPercentage, rate);
}
public void Dispose()
{
httpClient?.Dispose();
}
}