diff --git a/ArchiSteamFarm/ASF.cs b/ArchiSteamFarm/ASF.cs index d160dab50..34cfc9912 100644 --- a/ArchiSteamFarm/ASF.cs +++ b/ArchiSteamFarm/ASF.cs @@ -168,7 +168,7 @@ namespace ArchiSteamFarm { ArchiLogger.LogGenericInfo(string.Format(Strings.UpdateDownloadingNewVersion, newVersion, binaryAsset.Size / 1024 / 1024)); - byte[] result = await Program.WebBrowser.UrlGetToBytesRetry(binaryAsset.DownloadURL).ConfigureAwait(false); + byte[] result = await Program.WebBrowser.UrlGetToBytesWithProgressRetry(binaryAsset.DownloadURL).ConfigureAwait(false); if (result == null) { return null; } diff --git a/ArchiSteamFarm/ArchiSteamFarm.csproj b/ArchiSteamFarm/ArchiSteamFarm.csproj index d393d5071..52038c7df 100644 --- a/ArchiSteamFarm/ArchiSteamFarm.csproj +++ b/ArchiSteamFarm/ArchiSteamFarm.csproj @@ -3,8 +3,8 @@ Exe netcoreapp2.0 - 3.0.5.6 - 3.0.5.6 + 3.0.5.4 + 3.0.5.4 latest none ASF.ico diff --git a/ArchiSteamFarm/WebBrowser.cs b/ArchiSteamFarm/WebBrowser.cs index ebcf47e62..d9e742a4e 100644 --- a/ArchiSteamFarm/WebBrowser.cs +++ b/ArchiSteamFarm/WebBrowser.cs @@ -21,6 +21,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Net; using System.Net.Http; using System.Threading.Tasks; @@ -88,7 +89,7 @@ namespace ArchiSteamFarm { return htmlDocument; } - internal async Task UrlGetToBytesRetry(string request, string referer = null) { + internal async Task UrlGetToBytesWithProgressRetry(string request, string referer = null) { if (string.IsNullOrEmpty(request)) { ArchiLogger.LogNullError(nameof(request)); return null; @@ -96,7 +97,7 @@ namespace ArchiSteamFarm { byte[] result = null; for (byte i = 0; (i < MaxTries) && (result == null); i++) { - result = await UrlGetToBytes(request, referer).ConfigureAwait(false); + result = await UrlGetToBytesWithProgress(request, referer).ConfigureAwait(false); } if (result != null) { @@ -277,18 +278,54 @@ namespace ArchiSteamFarm { } } - private async Task UrlGetToBytes(string request, string referer = null) { + private async Task UrlGetToBytesWithProgress(string request, string referer = null) { if (string.IsNullOrEmpty(request)) { ArchiLogger.LogNullError(nameof(request)); return null; } - using (HttpResponseMessage httpResponse = await UrlGetToResponse(request, referer).ConfigureAwait(false)) { + const byte printPercentage = 10; + + using (HttpResponseMessage httpResponse = await UrlGetToResponse(request, referer, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false)) { if (httpResponse == null) { return null; } - return await httpResponse.Content.ReadAsByteArrayAsync().ConfigureAwait(false); + ASF.ArchiLogger.LogGenericDebug("0%..."); + + using (MemoryStream ms = new MemoryStream()) { + using (Stream contentStream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false)) { + long contentLength = httpResponse.Content.Headers.ContentLength.GetValueOrDefault(); + byte batch = 0; + uint readThisBatch = 0; + byte[] buffer = new byte[8192]; // This is HttpClient's buffer, using more doesn't make sense + + while (contentStream.CanRead) { + int read = await contentStream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); + if (read == 0) { + break; + } + + await ms.WriteAsync(buffer, 0, read).ConfigureAwait(false); + + if ((contentLength == 0) || (batch >= printPercentage)) { + continue; + } + + readThisBatch += (uint) read; + + if (readThisBatch < contentLength / printPercentage) { + continue; + } + + readThisBatch = 0; + ASF.ArchiLogger.LogGenericDebug(++batch * printPercentage + "%..."); + } + } + + ASF.ArchiLogger.LogGenericDebug("100%"); + return ms.ToArray(); + } } } @@ -337,13 +374,13 @@ namespace ArchiSteamFarm { return !string.IsNullOrEmpty(content) ? StringToHtmlDocument(content) : null; } - private async Task UrlGetToResponse(string request, string referer = null) { + private async Task UrlGetToResponse(string request, string referer = null, HttpCompletionOption httpCompletionOptions = HttpCompletionOption.ResponseContentRead) { if (string.IsNullOrEmpty(request)) { ArchiLogger.LogNullError(nameof(request)); return null; } - HttpResponseMessage result = await UrlRequest(new Uri(request), HttpMethod.Get, null, referer).ConfigureAwait(false); + HttpResponseMessage result = await UrlRequest(new Uri(request), HttpMethod.Get, null, referer, httpCompletionOptions).ConfigureAwait(false); return result; } @@ -445,7 +482,7 @@ namespace ArchiSteamFarm { return null; } - private async Task UrlRequest(Uri requestUri, HttpMethod httpMethod, IReadOnlyCollection> data = null, string referer = null, byte maxRedirections = MaxTries) { + private async Task UrlRequest(Uri requestUri, HttpMethod httpMethod, IReadOnlyCollection> data = null, string referer = null, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead, byte maxRedirections = MaxTries) { if ((requestUri == null) || (httpMethod == null)) { ArchiLogger.LogNullError(nameof(requestUri) + " || " + nameof(httpMethod)); return null; @@ -467,7 +504,7 @@ namespace ArchiSteamFarm { } try { - responseMessage = await HttpClient.SendAsync(requestMessage).ConfigureAwait(false); + responseMessage = await HttpClient.SendAsync(requestMessage, httpCompletionOption).ConfigureAwait(false); } catch (Exception e) { ArchiLogger.LogGenericDebuggingException(e); return null; @@ -512,7 +549,7 @@ namespace ArchiSteamFarm { } } - return await UrlRequest(redirectUri, httpMethod, data, referer, --maxRedirections).ConfigureAwait(false); + return await UrlRequest(redirectUri, httpMethod, data, referer, httpCompletionOption, --maxRedirections).ConfigureAwait(false); } } } \ No newline at end of file