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;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace ShareX.HelpersLib
|
namespace ShareX.HelpersLib
|
||||||
{
|
{
|
||||||
public class FileDownloader
|
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 URL { get; private set; }
|
||||||
public string DownloadLocation { get; private set; }
|
public string DownloadLocation { get; private set; }
|
||||||
public bool IsDownloading { get; private set; }
|
public bool IsDownloading { get; private set; }
|
||||||
public bool IsCanceled { get; private set; }
|
public bool IsCanceled { get; private set; }
|
||||||
public bool IsPaused { get; private set; }
|
|
||||||
public long FileSize { get; private set; }
|
public long FileSize { get; private set; }
|
||||||
public long DownloadedSize { get; private set; }
|
public long DownloadedSize { get; private set; }
|
||||||
public double DownloadSpeed { 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 string AcceptHeader { get; set; }
|
||||||
public Exception LastException { get; private set; }
|
public Exception LastException { get; private set; }
|
||||||
|
|
||||||
private const int bufferSize = 32768;
|
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;
|
URL = url;
|
||||||
DownloadLocation = downloadLocation;
|
DownloadLocation = downloadLocation;
|
||||||
Proxy = proxy;
|
|
||||||
AcceptHeader = acceptHeader;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartDownload()
|
public async Task StartDownload()
|
||||||
{
|
{
|
||||||
if (!IsDownloading && !string.IsNullOrEmpty(URL))
|
if (!IsDownloading && !string.IsNullOrEmpty(URL))
|
||||||
{
|
{
|
||||||
IsDownloading = true;
|
IsDownloading = true;
|
||||||
IsCanceled = false;
|
IsCanceled = false;
|
||||||
IsPaused = false;
|
|
||||||
|
|
||||||
Progress<EventHandler> progress = new Progress<EventHandler>(OnProgressChanged);
|
await DoWork();
|
||||||
Task.Run(() => DoWork(progress));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,110 +83,88 @@ public void StopDownload()
|
||||||
IsCanceled = true;
|
IsCanceled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PauseDownload()
|
private async Task DoWork()
|
||||||
{
|
|
||||||
IsPaused = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ResumeDownload()
|
|
||||||
{
|
|
||||||
IsPaused = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnProgressChanged(EventHandler eventHandler)
|
|
||||||
{
|
|
||||||
eventHandler?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DoWork(IProgress<EventHandler> progress)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
|
HttpClient client = HttpClientFactory.Create();
|
||||||
request.UserAgent = ShareXResources.UserAgent;
|
|
||||||
request.Proxy = Proxy;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(AcceptHeader))
|
using (HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, URL))
|
||||||
{
|
{
|
||||||
request.Accept = AcceptHeader;
|
if (!string.IsNullOrEmpty(AcceptHeader))
|
||||||
}
|
|
||||||
|
|
||||||
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
|
||||||
{
|
|
||||||
FileSize = response.ContentLength;
|
|
||||||
|
|
||||||
progress.Report(FileSizeReceived);
|
|
||||||
|
|
||||||
if (FileSize > 0)
|
|
||||||
{
|
{
|
||||||
Stopwatch timer = new Stopwatch();
|
requestMessage.Headers.Accept.ParseAdd(AcceptHeader);
|
||||||
Stopwatch progressEventTimer = new Stopwatch();
|
}
|
||||||
long speedTest = 0;
|
|
||||||
|
|
||||||
byte[] buffer = new byte[(int)Math.Min(bufferSize, FileSize)];
|
using (HttpResponseMessage responseMessage = await client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead))
|
||||||
int bytesRead;
|
{
|
||||||
|
responseMessage.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
using (FileStream fs = new FileStream(DownloadLocation, FileMode.Create, FileAccess.Write, FileShare.Read))
|
FileSize = responseMessage.Content.Headers.ContentLength ?? -1;
|
||||||
using (Stream responseStream = response.GetResponseStream())
|
|
||||||
|
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();
|
if (!timer.IsRunning)
|
||||||
Thread.Sleep(10);
|
{
|
||||||
}
|
timer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
if (IsCanceled)
|
if (!progressEventTimer.IsRunning)
|
||||||
{
|
{
|
||||||
return;
|
progressEventTimer.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!timer.IsRunning)
|
bytesRead = await responseStream.ReadAsync(buffer, 0, buffer.Length);
|
||||||
{
|
await fileStream.WriteAsync(buffer, 0, bytesRead);
|
||||||
timer.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!progressEventTimer.IsRunning)
|
DownloadedSize += bytesRead;
|
||||||
{
|
speedTest += bytesRead;
|
||||||
progressEventTimer.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
bytesRead = responseStream.Read(buffer, 0, buffer.Length);
|
if (timer.ElapsedMilliseconds > 500)
|
||||||
fs.Write(buffer, 0, bytesRead);
|
{
|
||||||
DownloadedSize += bytesRead;
|
DownloadSpeed = (double)speedTest / timer.ElapsedMilliseconds * 1000;
|
||||||
speedTest += bytesRead;
|
speedTest = 0;
|
||||||
|
timer.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
if (timer.ElapsedMilliseconds > 500)
|
if (progressEventTimer.ElapsedMilliseconds > 100)
|
||||||
{
|
{
|
||||||
DownloadSpeed = (double)speedTest / timer.ElapsedMilliseconds * 1000;
|
ProgressChanged?.Invoke();
|
||||||
speedTest = 0;
|
|
||||||
timer.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (progressEventTimer.ElapsedMilliseconds > 100)
|
progressEventTimer.Reset();
|
||||||
{
|
}
|
||||||
progress.Report(ProgressChanged);
|
|
||||||
|
|
||||||
progressEventTimer.Reset();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
progress.Report(ProgressChanged);
|
ProgressChanged?.Invoke();
|
||||||
progress.Report(DownloadCompleted);
|
DownloadCompleted?.Invoke();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
if (!IsCanceled)
|
if (!IsCanceled)
|
||||||
{
|
{
|
||||||
LastException = ex;
|
LastException = e;
|
||||||
|
|
||||||
progress.Report(ExceptionThrown);
|
ExceptionThrown?.Invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
|
|
@ -594,10 +594,10 @@ public static async Task DownloadFileAsync(string url, string filePath)
|
||||||
{
|
{
|
||||||
if (responseMessage.IsSuccessStatusCode)
|
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))
|
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();
|
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)
|
if (responseMessage.IsSuccessStatusCode && responseMessage.Content.Headers.ContentType != null)
|
||||||
{
|
{
|
||||||
|
@ -676,7 +676,8 @@ public static async Task<string> GetFileNameFromWebServerAsync(string url)
|
||||||
{
|
{
|
||||||
HttpClient client = HttpClientFactory.Create();
|
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)
|
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.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace ShareX.HelpersLib
|
namespace ShareX.HelpersLib
|
||||||
|
@ -42,7 +42,6 @@ public partial class DownloaderForm : Form
|
||||||
public string URL { get; set; }
|
public string URL { get; set; }
|
||||||
public string FileName { get; set; }
|
public string FileName { get; set; }
|
||||||
public string DownloadLocation { get; private set; }
|
public string DownloadLocation { get; private set; }
|
||||||
public IWebProxy Proxy { get; set; }
|
|
||||||
public string AcceptHeader { get; set; }
|
public string AcceptHeader { get; set; }
|
||||||
public bool AutoStartDownload { get; set; }
|
public bool AutoStartDownload { get; set; }
|
||||||
public InstallType InstallType { get; set; }
|
public InstallType InstallType { get; set; }
|
||||||
|
@ -57,7 +56,6 @@ private DownloaderForm()
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
ShareXResources.ApplyTheme(this);
|
ShareXResources.ApplyTheme(this);
|
||||||
|
|
||||||
Proxy = HelpersOptions.CurrentProxy.GetWebProxy();
|
|
||||||
ChangeStatus(Resources.DownloaderForm_DownloaderForm_Waiting_);
|
ChangeStatus(Resources.DownloaderForm_DownloaderForm_Waiting_);
|
||||||
Status = DownloaderFormStatus.Waiting;
|
Status = DownloaderFormStatus.Waiting;
|
||||||
AutoStartDownload = true;
|
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)
|
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 (e.Button == MouseButtons.Left)
|
||||||
{
|
{
|
||||||
if (Status == DownloaderFormStatus.Waiting)
|
if (Status == DownloaderFormStatus.Waiting)
|
||||||
{
|
{
|
||||||
StartDownload();
|
await StartDownload();
|
||||||
}
|
}
|
||||||
else if (Status == DownloaderFormStatus.DownloadCompleted)
|
else if (Status == DownloaderFormStatus.DownloadCompleted)
|
||||||
{
|
{
|
||||||
|
@ -131,6 +129,7 @@ private void RunInstallerWithDelay(int delay = 1000)
|
||||||
Thread.Sleep(delay);
|
Thread.Sleep(delay);
|
||||||
RunInstaller();
|
RunInstaller();
|
||||||
});
|
});
|
||||||
|
|
||||||
thread.Start();
|
thread.Start();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -197,17 +196,7 @@ private void ChangeStatus(string status)
|
||||||
lblStatus.Text = Helpers.SafeStringFormat(Resources.DownloaderForm_ChangeStatus_Status___0_, status);
|
lblStatus.Text = Helpers.SafeStringFormat(Resources.DownloaderForm_ChangeStatus_Status___0_, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ChangeProgress()
|
private async Task StartDownload()
|
||||||
{
|
|
||||||
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()
|
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(URL) && Status == DownloaderFormStatus.Waiting)
|
if (!string.IsNullOrEmpty(URL) && Status == DownloaderFormStatus.Waiting)
|
||||||
{
|
{
|
||||||
|
@ -220,19 +209,35 @@ private void StartDownload()
|
||||||
|
|
||||||
DebugHelper.WriteLine($"Downloading: \"{URL}\" -> \"{DownloadLocation}\"");
|
DebugHelper.WriteLine($"Downloading: \"{URL}\" -> \"{DownloadLocation}\"");
|
||||||
|
|
||||||
fileDownloader = new FileDownloader(URL, DownloadLocation, Proxy, AcceptHeader);
|
fileDownloader = new FileDownloader(URL, DownloadLocation);
|
||||||
fileDownloader.FileSizeReceived += (v1, v2) => ChangeProgress();
|
fileDownloader.AcceptHeader = AcceptHeader;
|
||||||
fileDownloader.DownloadStarted += (v1, v2) => ChangeStatus(Resources.DownloaderForm_StartDownload_Downloading_);
|
fileDownloader.FileSizeReceived += FileDownloader_ProgressChanged;
|
||||||
fileDownloader.ProgressChanged += (v1, v2) => ChangeProgress();
|
fileDownloader.DownloadStarted += FileDownloader_DownloadStarted;
|
||||||
fileDownloader.DownloadCompleted += fileDownloader_DownloadCompleted;
|
fileDownloader.ProgressChanged += FileDownloader_ProgressChanged;
|
||||||
fileDownloader.ExceptionThrown += (v1, v2) => ChangeStatus(fileDownloader.LastException.Message);
|
fileDownloader.DownloadCompleted += FileDownloader_DownloadCompleted;
|
||||||
fileDownloader.StartDownload();
|
fileDownloader.ExceptionThrown += FileDownloader_ExceptionThrown;
|
||||||
|
await fileDownloader.StartDownload();
|
||||||
|
|
||||||
ChangeStatus(Resources.DownloaderForm_StartDownload_Getting_file_size_);
|
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_);
|
ChangeStatus(Resources.DownloaderForm_fileDownloader_DownloadCompleted_Download_completed_);
|
||||||
Status = DownloaderFormStatus.DownloadCompleted;
|
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)
|
private void DownloaderForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||||
{
|
{
|
||||||
if (Status == DownloaderFormStatus.DownloadStarted && fileDownloader != null)
|
if (Status == DownloaderFormStatus.DownloadStarted && fileDownloader != null)
|
||||||
|
|
Loading…
Reference in a new issue