internal async Task <byte[]> ReadHttpResponseStreamAsync(HttpResponseMessage httpResponse, long?length, CancellationToken ct, bool saveToFile = false, string filename = null, string folderPath = null) { return(await Task.Run(async() => { // Were we already canceled? ct.ThrowIfCancellationRequested(); using (StreamReader sr = new StreamReader(await httpResponse.Content.ReadAsStreamAsync())) { DownloadMetric metric = new DownloadMetric(length); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); OnDownloadStart?.Invoke(metric); if (!saveToFile) { return FromReaderToStream(sr, new MemoryStream((int)length), ref metric, ref stopwatch, ref length, ct); } else { filename = ToRelativeFilePath(httpResponse.RequestMessage.RequestUri, filename, folderPath); return FromReaderToStream(sr, File.Open(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite), ref metric, ref stopwatch, ref length, ct); } } }, ct)); }
public void QueueDownload(UriString url, string targetDirectory, string filename = null, int retryCount = 0) { var download = new DownloadTask(TaskManager, url, targetDirectory, filename, retryCount, Token); download.OnStart += t => OnDownloadStart?.Invoke(((DownloadTask)t).Url); download.OnEnd += (t, res, s, ex) => { if (s) { OnDownloadComplete?.Invoke(((DownloadTask)t).Url, res); } else { OnDownloadFailed?.Invoke(((DownloadTask)t).Url, ex); } }; // queue after hooking up events so OnDownload* gets called first Queue(download); }
public void QueueDownload(UriString url, NPath targetDirectory) { var download = new DownloadTask(Token, fileSystem, url, targetDirectory); download.OnStart += t => OnDownloadStart?.Invoke(((DownloadTask)t).Url); download.OnEnd += (t, res, s, ex) => { if (s) { OnDownloadComplete?.Invoke(((DownloadTask)t).Url, res); } else { OnDownloadFailed?.Invoke(((DownloadTask)t).Url, ex); } }; // queue after hooking up events so OnDownload* gets called first Queue(download); }
/// <summary> /// From a provided REST API endpoint download a mod. /// </summary> public async Task DownloadMod(string url) { Downloading = true; string modZipPath; string modImagePath; string modExtractPath; string modString = string.Empty; using (WebClient wc = new WebClient()) { dynamic Data = new OnDownloadCompleteArgs(); OnDownloadStart?.Invoke(this, Data); wc.DownloadProgressChanged += WCDownloadPercentChanged; try { modString = await wc.DownloadStringTaskAsync(url); } catch (WebException ex) { Data.ErrorMessage = ex.Message; OnDownloadComplete?.Invoke(this, Data); return; } JsonObject json = JsonObject.Parse(modString); // Let's make sure the slug doesn't have weird stuff. json["slug"] = string.Join(" ", json["slug"].Split(Path.GetInvalidFileNameChars().Concat(Path.GetInvalidPathChars()).ToArray())); if (json["compatible"] != "Yes") { Data.ErrorMessage = Helpers._("Error.NotCompatible"); OnDownloadComplete?.Invoke(this, Data); return; } m = new Mod( json["id"], json.ArrayObjects("title") [0]["rendered"], DateTime.ParseExact(json["modified"].Replace("T", " "), "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture), json.ArrayObjects("content") [0]["rendered"], json["author_name"], url, json["File"], json["slug"], json["slug"] + ".jpg" ); modZipPath = zipPath + m.Slug + ".zip"; modExtractPath = Mod.InstallPath + m.Slug + "\\"; modImagePath = Mod.ImagePath + m.Thumbnail; // Cleanup previous versions and files. Delete(m.Slug); if (File.Exists(modZipPath)) { File.Delete(modZipPath); } if (Directory.Exists(modExtractPath)) { Directory.Delete(modExtractPath, true); } if (File.Exists(modImagePath)) { File.Delete(modImagePath); } // And start downloading stuff. try { await wc.DownloadFileTaskAsync(new System.Uri(json["image"]), modImagePath); } catch (WebException we) { Data.ErrorMessage = we.Message; OnDownloadComplete?.Invoke(this, Data); return; } try { await wc.DownloadFileTaskAsync(new System.Uri(m.File), modZipPath); } catch (WebException we) { Data.ErrorMessage = we.Message; OnDownloadComplete?.Invoke(this, Data); return; } UnpackMod(modZipPath, modExtractPath); AvailableMods.Add(m); Data.Success = true; OnDownloadComplete?.Invoke(this, Data); UpdateSettings(); } Downloading = false; }
private async Task ProcessDownloadAsync(Uri uri, string filename, CancellationToken ct) { try { dynamic request = null; #region Get file size if (uri.Scheme == Uri.UriSchemeHttp) { request = WebRequest.Create(uri) as HttpWebRequest; request !.Method = WebRequestMethods.Http.Head; } else if (uri.Scheme == Uri.UriSchemeFtp) { request = WebRequest.Create(uri) as FtpWebRequest; request !.Method = WebRequestMethods.Ftp.GetFileSize; } var metric = new DownloaderMetric { FileName = Path.GetFileName(filename) }; using (var response = await request !.GetResponseAsync()) { metric.TotalBytes = response.ContentLength; } #endregion // Set start download position long startPos = 0; var fi = new FileInfo(filename); if (fi.Exists) { if (metric.TotalBytes > fi.Length) { metric.DownloadedBytes = startPos = fi.Length - 1024; } else if (metric.TotalBytes == fi.Length) { return; } } #region Read Content Stream Asynchronously if (uri.Scheme == Uri.UriSchemeHttp) { request = WebRequest.Create(uri) as HttpWebRequest; request = (HttpWebRequest)request; request !.Method = WebRequestMethods.Http.Get; request.AddRange(startPos, metric.TotalBytes); } else if (uri.Scheme == Uri.UriSchemeFtp) { request = WebRequest.Create(uri) as FtpWebRequest; request !.Method = WebRequestMethods.Ftp.DownloadFile; request.ContentOffset = startPos; } var stopwatch = new Stopwatch(); stopwatch.Start(); if (!Directory.Exists(Path.GetDirectoryName(filename))) { Directory.CreateDirectory(Path.GetDirectoryName(filename) !); } var fileStream = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite) { Position = metric.DownloadedBytes }; await Task.Run(async() => { if (ct.IsCancellationRequested) { return; } using var streamReader = new StreamReader((await request.GetResponseAsync()).GetResponseStream()); OnDownloadStart?.Invoke(metric); FromReaderToFile(streamReader, fileStream, ref metric, ref stopwatch, ct); OnDownloadCompleted?.Invoke(metric); }, ct); #endregion } catch (OperationCanceledException) { const string msg = "Download cancelled by user"; OnError?.Invoke(new DownloaderClientException(msg)); } catch (Exception ex) { const string msg = "An unexpected error occurred."; OnError?.Invoke( new DownloaderClientException($"{msg}\n\nDownload failed. See inner exception for details.", ex)); } }
private async void DownloadWithUrl(string _url) { var _filePath = new Uri(_url).AbsolutePath; var _name = Path.GetFileName(_filePath); var _dir = $"./downloads/{Path.GetDirectoryName(_filePath)}"; var _path = $"{_dir}/{_name}"; if (!Directory.Exists(_dir)) { Directory.CreateDirectory(_dir); } if (File.Exists(_path)) { OnDownloadComplete?.Invoke(this, new DownloadResultEventArg { FileName = _name, Success = true, Url = _url, Contains = true }); } else { try { OnDownloadStart?.Invoke(this, new DownloadResultEventArg { FileName = _name, Success = true, Url = _url }); HttpWebRequest webRequest = WebRequest.CreateHttp(_url); webRequest.UserAgent = "Half-Life 2"; webRequest.Referer = "hl2://31.186.251.23:27016"; using (WebResponse _request = webRequest.GetResponse()) using (Stream _stream = _request.GetResponseStream()) using (FileStream _file = File.Create(_path)) await _stream.CopyToAsync(_file); OnDownloadComplete?.Invoke(this, new DownloadResultEventArg { FileName = _name, Success = true, Url = _url }); } catch (Exception ex) { //WebException _ex = ex as WebException; if (_retryCount++ < 3) { File.Delete(_path); DownloadWithUrl(_url); } else { _retryCount = 0; OnDownloadComplete?.Invoke(this, new DownloadResultEventArg { FileName = _name, Success = false, Url = _url, Exception = ex }); } } } }
internal async Task <byte[]> ProcessDownloadAsync(Uri uri, Stream output, CancellationToken ct) { byte[] vs = Array.Empty <byte>(); try { #region Get file size DownloadTrace?.Invoke("Getting file size..."); WebRequest webRequest = WebRequest.Create(uri); webRequest.Method = "HEAD"; Stopwatch watch = new Stopwatch(); DownloadMetric m = new DownloadMetric(); long? bytes; watch.Start(); using (WebResponse webResponse = webRequest.GetResponse()) { bytes = long.Parse(webResponse.Headers.Get("Content-Length")); DownloadTrace?.Invoke($"File size: {bytes.Value.HumanizeBytes(2)}"); m.TotalBytes = bytes.Value; m.ElapsedTime = watch.Elapsed; } /*__________________________________________________________________________________ | | | .NET runtime has a 2GB size limit for objects. | | ---------------------------------------------- | | To adhere to this restriction, this module ONLY allows downloading files | | less than 1GB. If the file is greater than 1GB, call DownloadToFile method | | instead which downloads the file directly to disk or allow this application | | to automatically save the file to disk for you. | | ---------------------------------------------- | | 1 GB = 1,000,000,000 (1 Billion Bytes). | | | *|________________________________________________________________________________|*/ if (bytes == null) { bytes = _maxDowloadSize; } else { if (bytes.Value > _maxDowloadSize) { bytes = _maxDowloadSize; } } #endregion #region Read Content Stream Asynchronously long?l = bytes; DownloadTrace?.Invoke("Download about to begin."); DownloadTrace.Invoke("On your marks..."); HttpWebRequest req = WebRequest.Create(uri) as HttpWebRequest; req.Method = "GET"; req.AddRange(0, bytes.Value); vs = await Task.Run(async() => { // Check if operation is already canceled? ct.ThrowIfCancellationRequested(); using (StreamReader sr = new StreamReader((await req.GetResponseAsync()).GetResponseStream())) { DownloadTrace.Invoke("Download started!"); OnDownloadStart?.Invoke(m); var a = FromReaderToStream(sr, output, ref m, ref watch, ref l, ct); DownloadCompleted?.Invoke(m, null); return(a); } }, ct); #endregion } catch (OperationCanceledException) { string msg = "Download cancelled by user"; DownloadTrace.Invoke(msg); OnError?.Invoke(new DownloadClientException(msg)); } catch (Exception ex) { string msg = "An unexpected error occured."; DownloadTrace?.Invoke(msg); OnError?.Invoke(new DownloadClientException($"{msg}\n\nDownload failed. See inner exception for details.", ex)); } return(vs); }