private static async Task <long> GetFileSizeAsync(string url) { using var httpRequestMessage = new HttpRequestMessage(); if (!url.Contains("platform=android_tv_yst") && !url.Contains("platform=android")) { httpRequestMessage.Headers.TryAddWithoutValidation("Referer", "https://www.bilibili.com"); } httpRequestMessage.Headers.TryAddWithoutValidation("User-Agent", "Mozilla/5.0"); httpRequestMessage.Headers.TryAddWithoutValidation("Cookie", Core.Config.COOKIE); httpRequestMessage.RequestUri = new(url); var response = (await AppHttpClient.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseHeadersRead)).EnsureSuccessStatusCode(); long totalSizeBytes = response.Content.Headers.ContentLength ?? 0; return(totalSizeBytes); }
private static async Task RangeDownloadToTmpAsync(int id, string url, string tmpName, long fromPosition, long?toPosition, Action <int, long, long> onProgress, bool failOnRangeNotSupported = false) { DateTimeOffset?lastTime = File.Exists(tmpName) ? new FileInfo(tmpName).LastWriteTimeUtc : null; using (var fileStream = new FileStream(tmpName, FileMode.Create)) { fileStream.Seek(0, SeekOrigin.End); var downloadedBytes = fromPosition + fileStream.Position; using var httpRequestMessage = new HttpRequestMessage(); if (!url.Contains("platform=android_tv_yst") && !url.Contains("platform=android")) { httpRequestMessage.Headers.TryAddWithoutValidation("Referer", "https://www.bilibili.com"); } httpRequestMessage.Headers.TryAddWithoutValidation("User-Agent", "Mozilla/5.0"); httpRequestMessage.Headers.TryAddWithoutValidation("Cookie", Core.Config.COOKIE); httpRequestMessage.Headers.Range = new(downloadedBytes, toPosition); httpRequestMessage.Headers.IfRange = lastTime != null ? new(lastTime.Value) : null; httpRequestMessage.RequestUri = new(url); using var response = (await AppHttpClient.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseHeadersRead)).EnsureSuccessStatusCode(); if (response.StatusCode == HttpStatusCode.OK) // server doesn't response a partial content { if (failOnRangeNotSupported && (downloadedBytes > 0 || toPosition != null)) { throw new NotSupportedException("Range request is not supported."); } downloadedBytes = 0; fileStream.Seek(0, SeekOrigin.Begin); } using var stream = await response.Content.ReadAsStreamAsync(); var totalBytes = downloadedBytes + (response.Content.Headers.ContentLength ?? long.MaxValue - downloadedBytes); const int blockSize = 1048576 / 4; var buffer = new byte[blockSize]; while (downloadedBytes < totalBytes) { var recevied = await stream.ReadAsync(buffer); if (recevied == 0) { break; } await fileStream.WriteAsync(buffer.AsMemory(0, recevied)); await fileStream.FlushAsync(); downloadedBytes += recevied; onProgress(id, downloadedBytes - fromPosition, totalBytes); } if (response.Content.Headers.ContentLength != null && (response.Content.Headers.ContentLength != new FileInfo(tmpName).Length)) { throw new Exception("Retry..."); } } }