mirror of
https://github.com/ShareX/ShareX.git
synced 2024-09-28 23:42:13 +12:00
Use HttpClient in FileDownloader class
This commit is contained in:
parent
7085012fd4
commit
bbb3d108f3
3 changed files with 100 additions and 118 deletions
|
@ -26,21 +26,19 @@ You should have received a copy of the GNU General Public License
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShareX.HelpersLib
|
||||
{
|
||||
public class FileDownloader
|
||||
{
|
||||
public event EventHandler FileSizeReceived, DownloadStarted, ProgressChanged, DownloadCompleted, ExceptionThrown;
|
||||
public event Action FileSizeReceived, DownloadStarted, ProgressChanged, DownloadCompleted, ExceptionThrown;
|
||||
|
||||
public string URL { get; private set; }
|
||||
public string DownloadLocation { get; private set; }
|
||||
public bool IsDownloading { get; private set; }
|
||||
public bool IsCanceled { get; private set; }
|
||||
public bool IsPaused { get; private set; }
|
||||
public long FileSize { get; private set; }
|
||||
public long DownloadedSize { get; private set; }
|
||||
public double DownloadSpeed { get; private set; }
|
||||
|
@ -58,30 +56,25 @@ public double DownloadPercentage
|
|||
}
|
||||
}
|
||||
|
||||
public IWebProxy Proxy { get; set; }
|
||||
public string AcceptHeader { get; set; }
|
||||
public Exception LastException { get; private set; }
|
||||
|
||||
private const int bufferSize = 32768;
|
||||
|
||||
public FileDownloader(string url, string downloadLocation, IWebProxy proxy = null, string acceptHeader = null)
|
||||
public FileDownloader(string url, string downloadLocation)
|
||||
{
|
||||
URL = url;
|
||||
DownloadLocation = downloadLocation;
|
||||
Proxy = proxy;
|
||||
AcceptHeader = acceptHeader;
|
||||
}
|
||||
|
||||
public void StartDownload()
|
||||
public async Task StartDownload()
|
||||
{
|
||||
if (!IsDownloading && !string.IsNullOrEmpty(URL))
|
||||
{
|
||||
IsDownloading = true;
|
||||
IsCanceled = false;
|
||||
IsPaused = false;
|
||||
|
||||
Progress<EventHandler> progress = new Progress<EventHandler>(OnProgressChanged);
|
||||
Task.Run(() => DoWork(progress));
|
||||
await DoWork();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,110 +83,88 @@ public void StopDownload()
|
|||
IsCanceled = true;
|
||||
}
|
||||
|
||||
public void PauseDownload()
|
||||
{
|
||||
IsPaused = true;
|
||||
}
|
||||
|
||||
public void ResumeDownload()
|
||||
{
|
||||
IsPaused = false;
|
||||
}
|
||||
|
||||
private void OnProgressChanged(EventHandler eventHandler)
|
||||
{
|
||||
eventHandler?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void DoWork(IProgress<EventHandler> progress)
|
||||
private async Task DoWork()
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
|
||||
request.UserAgent = ShareXResources.UserAgent;
|
||||
request.Proxy = Proxy;
|
||||
HttpClient client = HttpClientFactory.Create();
|
||||
|
||||
if (!string.IsNullOrEmpty(AcceptHeader))
|
||||
using (HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, URL))
|
||||
{
|
||||
request.Accept = AcceptHeader;
|
||||
}
|
||||
|
||||
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
||||
{
|
||||
FileSize = response.ContentLength;
|
||||
|
||||
progress.Report(FileSizeReceived);
|
||||
|
||||
if (FileSize > 0)
|
||||
if (!string.IsNullOrEmpty(AcceptHeader))
|
||||
{
|
||||
Stopwatch timer = new Stopwatch();
|
||||
Stopwatch progressEventTimer = new Stopwatch();
|
||||
long speedTest = 0;
|
||||
requestMessage.Headers.Accept.ParseAdd(AcceptHeader);
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[(int)Math.Min(bufferSize, FileSize)];
|
||||
int bytesRead;
|
||||
using (HttpResponseMessage responseMessage = await client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead))
|
||||
{
|
||||
responseMessage.EnsureSuccessStatusCode();
|
||||
|
||||
using (FileStream fs = new FileStream(DownloadLocation, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
using (Stream responseStream = response.GetResponseStream())
|
||||
FileSize = responseMessage.Content.Headers.ContentLength ?? -1;
|
||||
|
||||
FileSizeReceived?.Invoke();
|
||||
|
||||
if (FileSize > 0)
|
||||
{
|
||||
progress.Report(DownloadStarted);
|
||||
Stopwatch timer = new Stopwatch();
|
||||
Stopwatch progressEventTimer = new Stopwatch();
|
||||
long speedTest = 0;
|
||||
|
||||
while (DownloadedSize < FileSize && !IsCanceled)
|
||||
byte[] buffer = new byte[(int)Math.Min(bufferSize, FileSize)];
|
||||
int bytesRead;
|
||||
|
||||
using (Stream responseStream = await responseMessage.Content.ReadAsStreamAsync())
|
||||
using (FileStream fileStream = new FileStream(DownloadLocation, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
{
|
||||
while (IsPaused && !IsCanceled)
|
||||
DownloadStarted?.Invoke();
|
||||
|
||||
while (DownloadedSize < FileSize && !IsCanceled)
|
||||
{
|
||||
timer.Reset();
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
if (!timer.IsRunning)
|
||||
{
|
||||
timer.Start();
|
||||
}
|
||||
|
||||
if (IsCanceled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!progressEventTimer.IsRunning)
|
||||
{
|
||||
progressEventTimer.Start();
|
||||
}
|
||||
|
||||
if (!timer.IsRunning)
|
||||
{
|
||||
timer.Start();
|
||||
}
|
||||
bytesRead = await responseStream.ReadAsync(buffer, 0, buffer.Length);
|
||||
await fileStream.WriteAsync(buffer, 0, bytesRead);
|
||||
|
||||
if (!progressEventTimer.IsRunning)
|
||||
{
|
||||
progressEventTimer.Start();
|
||||
}
|
||||
DownloadedSize += bytesRead;
|
||||
speedTest += bytesRead;
|
||||
|
||||
bytesRead = responseStream.Read(buffer, 0, buffer.Length);
|
||||
fs.Write(buffer, 0, bytesRead);
|
||||
DownloadedSize += bytesRead;
|
||||
speedTest += bytesRead;
|
||||
if (timer.ElapsedMilliseconds > 500)
|
||||
{
|
||||
DownloadSpeed = (double)speedTest / timer.ElapsedMilliseconds * 1000;
|
||||
speedTest = 0;
|
||||
timer.Reset();
|
||||
}
|
||||
|
||||
if (timer.ElapsedMilliseconds > 500)
|
||||
{
|
||||
DownloadSpeed = (double)speedTest / timer.ElapsedMilliseconds * 1000;
|
||||
speedTest = 0;
|
||||
timer.Reset();
|
||||
}
|
||||
if (progressEventTimer.ElapsedMilliseconds > 100)
|
||||
{
|
||||
ProgressChanged?.Invoke();
|
||||
|
||||
if (progressEventTimer.ElapsedMilliseconds > 100)
|
||||
{
|
||||
progress.Report(ProgressChanged);
|
||||
|
||||
progressEventTimer.Reset();
|
||||
progressEventTimer.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
progress.Report(ProgressChanged);
|
||||
progress.Report(DownloadCompleted);
|
||||
ProgressChanged?.Invoke();
|
||||
DownloadCompleted?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception e)
|
||||
{
|
||||
if (!IsCanceled)
|
||||
{
|
||||
LastException = ex;
|
||||
LastException = e;
|
||||
|
||||
progress.Report(ExceptionThrown);
|
||||
ExceptionThrown?.Invoke();
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
|
|
@ -594,10 +594,10 @@ public static async Task DownloadFileAsync(string url, string filePath)
|
|||
{
|
||||
if (responseMessage.IsSuccessStatusCode)
|
||||
{
|
||||
using (Stream stream = await responseMessage.Content.ReadAsStreamAsync())
|
||||
using (Stream responseStream = await responseMessage.Content.ReadAsStreamAsync())
|
||||
using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
await stream.CopyToAsync(fileStream);
|
||||
await responseStream.CopyToAsync(fileStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -632,7 +632,7 @@ public static async Task<Bitmap> DownloadImageAsync(string url)
|
|||
{
|
||||
HttpClient client = HttpClientFactory.Create();
|
||||
|
||||
using (HttpResponseMessage responseMessage = await client.GetAsync(url))
|
||||
using (HttpResponseMessage responseMessage = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
|
||||
{
|
||||
if (responseMessage.IsSuccessStatusCode && responseMessage.Content.Headers.ContentType != null)
|
||||
{
|
||||
|
@ -676,7 +676,8 @@ public static async Task<string> GetFileNameFromWebServerAsync(string url)
|
|||
{
|
||||
HttpClient client = HttpClientFactory.Create();
|
||||
|
||||
using (HttpResponseMessage responseMessage = await client.SendAsync(new HttpRequestMessage(HttpMethod.Head, url)))
|
||||
using (HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Head, url))
|
||||
using (HttpResponseMessage responseMessage = await client.SendAsync(requestMessage))
|
||||
{
|
||||
if (responseMessage.Content.Headers.ContentDisposition != null)
|
||||
{
|
||||
|
|
|
@ -28,8 +28,8 @@ You should have received a copy of the GNU General Public License
|
|||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace ShareX.HelpersLib
|
||||
|
@ -42,7 +42,6 @@ public partial class DownloaderForm : Form
|
|||
public string URL { get; set; }
|
||||
public string FileName { get; set; }
|
||||
public string DownloadLocation { get; private set; }
|
||||
public IWebProxy Proxy { get; set; }
|
||||
public string AcceptHeader { get; set; }
|
||||
public bool AutoStartDownload { get; set; }
|
||||
public InstallType InstallType { get; set; }
|
||||
|
@ -57,7 +56,6 @@ private DownloaderForm()
|
|||
InitializeComponent();
|
||||
ShareXResources.ApplyTheme(this);
|
||||
|
||||
Proxy = HelpersOptions.CurrentProxy.GetWebProxy();
|
||||
ChangeStatus(Resources.DownloaderForm_DownloaderForm_Waiting_);
|
||||
Status = DownloaderFormStatus.Waiting;
|
||||
AutoStartDownload = true;
|
||||
|
@ -81,21 +79,21 @@ public DownloaderForm(UpdateChecker updateChecker) : this(updateChecker.Download
|
|||
}
|
||||
}
|
||||
|
||||
private void DownloaderForm_Shown(object sender, EventArgs e)
|
||||
private async void DownloaderForm_Shown(object sender, EventArgs e)
|
||||
{
|
||||
if (AutoStartDownload)
|
||||
{
|
||||
StartDownload();
|
||||
await StartDownload();
|
||||
}
|
||||
}
|
||||
|
||||
private void btnAction_MouseClick(object sender, MouseEventArgs e)
|
||||
private async void btnAction_MouseClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.Button == MouseButtons.Left)
|
||||
{
|
||||
if (Status == DownloaderFormStatus.Waiting)
|
||||
{
|
||||
StartDownload();
|
||||
await StartDownload();
|
||||
}
|
||||
else if (Status == DownloaderFormStatus.DownloadCompleted)
|
||||
{
|
||||
|
@ -131,6 +129,7 @@ private void RunInstallerWithDelay(int delay = 1000)
|
|||
Thread.Sleep(delay);
|
||||
RunInstaller();
|
||||
});
|
||||
|
||||
thread.Start();
|
||||
}
|
||||
else
|
||||
|
@ -197,17 +196,7 @@ private void ChangeStatus(string status)
|
|||
lblStatus.Text = Helpers.SafeStringFormat(Resources.DownloaderForm_ChangeStatus_Status___0_, status);
|
||||
}
|
||||
|
||||
private void ChangeProgress()
|
||||
{
|
||||
if (fileDownloader != null)
|
||||
{
|
||||
pbProgress.Value = (int)Math.Round(fileDownloader.DownloadPercentage);
|
||||
lblProgress.Text = Helpers.SafeStringFormat(CultureInfo.CurrentCulture, Resources.DownloaderForm_ChangeProgress_Progress,
|
||||
fileDownloader.DownloadPercentage, fileDownloader.DownloadSpeed / 1024, fileDownloader.DownloadedSize / 1024, fileDownloader.FileSize / 1024);
|
||||
}
|
||||
}
|
||||
|
||||
private void StartDownload()
|
||||
private async Task StartDownload()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(URL) && Status == DownloaderFormStatus.Waiting)
|
||||
{
|
||||
|
@ -220,19 +209,35 @@ private void StartDownload()
|
|||
|
||||
DebugHelper.WriteLine($"Downloading: \"{URL}\" -> \"{DownloadLocation}\"");
|
||||
|
||||
fileDownloader = new FileDownloader(URL, DownloadLocation, Proxy, AcceptHeader);
|
||||
fileDownloader.FileSizeReceived += (v1, v2) => ChangeProgress();
|
||||
fileDownloader.DownloadStarted += (v1, v2) => ChangeStatus(Resources.DownloaderForm_StartDownload_Downloading_);
|
||||
fileDownloader.ProgressChanged += (v1, v2) => ChangeProgress();
|
||||
fileDownloader.DownloadCompleted += fileDownloader_DownloadCompleted;
|
||||
fileDownloader.ExceptionThrown += (v1, v2) => ChangeStatus(fileDownloader.LastException.Message);
|
||||
fileDownloader.StartDownload();
|
||||
fileDownloader = new FileDownloader(URL, DownloadLocation);
|
||||
fileDownloader.AcceptHeader = AcceptHeader;
|
||||
fileDownloader.FileSizeReceived += FileDownloader_ProgressChanged;
|
||||
fileDownloader.DownloadStarted += FileDownloader_DownloadStarted;
|
||||
fileDownloader.ProgressChanged += FileDownloader_ProgressChanged;
|
||||
fileDownloader.DownloadCompleted += FileDownloader_DownloadCompleted;
|
||||
fileDownloader.ExceptionThrown += FileDownloader_ExceptionThrown;
|
||||
await fileDownloader.StartDownload();
|
||||
|
||||
ChangeStatus(Resources.DownloaderForm_StartDownload_Getting_file_size_);
|
||||
}
|
||||
}
|
||||
|
||||
private void fileDownloader_DownloadCompleted(object sender, EventArgs e)
|
||||
private void FileDownloader_DownloadStarted()
|
||||
{
|
||||
ChangeStatus(Resources.DownloaderForm_StartDownload_Downloading_);
|
||||
}
|
||||
|
||||
private void FileDownloader_ProgressChanged()
|
||||
{
|
||||
if (fileDownloader != null)
|
||||
{
|
||||
pbProgress.Value = (int)Math.Round(fileDownloader.DownloadPercentage);
|
||||
lblProgress.Text = Helpers.SafeStringFormat(CultureInfo.CurrentCulture, Resources.DownloaderForm_ChangeProgress_Progress,
|
||||
fileDownloader.DownloadPercentage, fileDownloader.DownloadSpeed / 1024, fileDownloader.DownloadedSize / 1024, fileDownloader.FileSize / 1024);
|
||||
}
|
||||
}
|
||||
|
||||
private void FileDownloader_DownloadCompleted()
|
||||
{
|
||||
ChangeStatus(Resources.DownloaderForm_fileDownloader_DownloadCompleted_Download_completed_);
|
||||
Status = DownloaderFormStatus.DownloadCompleted;
|
||||
|
@ -244,6 +249,11 @@ private void fileDownloader_DownloadCompleted(object sender, EventArgs e)
|
|||
}
|
||||
}
|
||||
|
||||
private void FileDownloader_ExceptionThrown()
|
||||
{
|
||||
ChangeStatus(fileDownloader.LastException.Message);
|
||||
}
|
||||
|
||||
private void DownloaderForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
if (Status == DownloaderFormStatus.DownloadStarted && fileDownloader != null)
|
||||
|
|
Loading…
Reference in a new issue