public class HttpClientDownloadWithProgress : IDisposable
{
private string _downloadUrl;
private string _destinationFilePath;
private bool disposedValue;
private readonly HttpClient _httpClient = new HttpClient { Timeout = TimeSpan.FromDays(1) };
public string DownloadUrl { get => _downloadUrl; set => _downloadUrl = value; }
public string DestinationFilePath { get => _destinationFilePath; set => _destinationFilePath = value; }
public delegate void ProgressChangedHandler(long? totalFileSize, long totalBytesDownloaded, double? progressPercentage);
public event ProgressChangedHandler ProgressChanged;
public HttpClientDownloadWithProgress()
{
}
public HttpClientDownloadWithProgress(string downloadUrl, string destinationFilePath)
{
DownloadUrl = downloadUrl;
DestinationFilePath = destinationFilePath;
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: 관리형 상태(관리형 개체)를 삭제합니다.
_httpClient?.Dispose();
}
// TODO: 비관리형 리소스(비관리형 개체)를 해제하고 종료자를 재정의합니다.
// TODO: 큰 필드를 null로 설정합니다.
disposedValue = true;
}
}
// // TODO: 비관리형 리소스를 해제하는 코드가 'Dispose(bool disposing)'에 포함된 경우에만 종료자를 재정의합니다.
// ~HttpClientDownloadWithProgress()
// {
// // 이 코드를 변경하지 마세요. 'Dispose(bool disposing)' 메서드에 정리 코드를 입력합니다.
// Dispose(disposing: false);
// }
public void Dispose()
{
// 이 코드를 변경하지 마세요. 'Dispose(bool disposing)' 메서드에 정리 코드를 입력합니다.
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
public async Task StartDownload()
{
if (string.IsNullOrEmpty(_downloadUrl) || string.IsNullOrEmpty(_destinationFilePath))
throw new ArgumentNullException($"{nameof(DownloadUrl)} 또는 {nameof(DestinationFilePath)}", $"값이 비어있습니다.");
using (var response = await _httpClient.GetAsync(DownloadUrl, HttpCompletionOption.ResponseHeadersRead))
await DownloadFileFromHttpResponseMessage(response);
}
private async Task DownloadFileFromHttpResponseMessage(HttpResponseMessage response)
{
response.EnsureSuccessStatusCode();
var totalBytes = response.Content.Headers.ContentLength;
using (var contentStream = await response.Content.ReadAsStreamAsync())
await ProcessContentStream(totalBytes, contentStream);
}
private 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);
}
}
private void TriggerProgressChanged(long? totalDownloadSize, long totalBytesRead)
{
if (ProgressChanged == null)
return;
double? progressPercentage = null;
if (totalDownloadSize.HasValue)
progressPercentage = Math.Round((double)totalBytesRead / totalDownloadSize.Value * 100, 2);
ProgressChanged(totalDownloadSize, totalBytesRead, progressPercentage);
}
}
참고 : https://github.com/dotnet/runtime/issues/16681#issuecomment-195980023
Progress while downloading a large file with HttpClient · Issue #16681 · dotnet/runtime
Hi All, Googling around I found that Windows.Web.Http.HttpClient provides a way to get progress of a download. Is there an way to get some kind of progress information when downloading a large file...
github.com
참고 : c# - Progress bar with HttpClient - Stack Overflow
Progress bar with HttpClient
i have a file downloader function: HttpClientHandler aHandler = new HttpClientHandler(); aHandler.ClientCertificateOptions = ClientCertificateOption.Automatic; HttpClient a...
stackoverflow.com
'C#' 카테고리의 다른 글
[C#] PublishSingleFile (0) | 2022.11.11 |
---|---|
[C#] WPF에서 Windows.Graphics.Capture 사용하여 디스플레이, 프로그램 Screen Capture 사용, NET Framework, NET6 모두 사용. (0) | 2022.08.19 |
[C#] EF Core 간단 사용. (0) | 2022.05.26 |
[C#] .NET 6 - Worker Service Environment.Exit (0) | 2022.04.27 |
[C#] string.Create (0) | 2022.02.23 |