WebClient 不遵循 .Net Core 3.1 中的重定向
WebClient is not following redirects in .Net Core 3.1
我尝试下载一个 URL 的文件 returns 一个 307 重定向代码。
我尝试使用 WebClient.DownloadFile
方法,但它似乎不遵循所请求站点的重定向。我通过搜索这个问题找到的东西要么说它应该工作(Microsoft 文档)要么没有真正回答我的问题:WebClient Does not automatically redirect
我的第一个问题是为什么它不遵循重定向,即使它使用的 HttpWebRequest AllowAutoRedirect=true
?
我的第二个问题是如何最好地实现使用自动重定向下载文件的功能。
我使用的示例 URL 是:https://api.spiget.org/v2/resources/10905/download
但是这个 URL 并不总是重定向,我猜这取决于一些内部 API 状态。
这是一个简单的例子 HttpClient
.NET Core 3.1 控制台应用程序(UPD: 添加了进度报告)
class Program
{
private static readonly HttpClient client = new HttpClient(new HttpClientHandler() { AllowAutoRedirect = true });
static async Task Main(string[] args)
{
try
{
IProgress<int> progress = new Progress<int>(p =>
{
Console.Write(p + " ");
});
await DownloadAndSaveFileAsync("https://api.spiget.org/v2/resources/10905/download", progress);
Console.WriteLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine("Done.");
Console.ReadKey();
}
private static async Task DownloadAndSaveFileAsync(string url, IProgress<int> progress)
{
using HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
response.EnsureSuccessStatusCode(); // throw if not success
string fileName = response.Content.Headers.ContentDisposition?.FileName ?? throw new Exception("Nothing to download");
fileName = fileName.Trim('\"'); // remove quotes
long contentLength = response.Content.Headers.ContentLength ?? 0;
Console.WriteLine("File: {0}", fileName);
Console.WriteLine("Content-Length: {0} bytes", contentLength);
using Stream responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
using FileStream fileStream = File.Create(fileName);
int bufferSize = 65536;
byte[] buffer = new byte[bufferSize];
int bytesRead;
long position = 0;
int storedPercentage = -1;
while ((bytesRead = await responseStream.ReadAsync(buffer, 0, bufferSize)) > 0)
{
await fileStream.WriteAsync(buffer, 0, bufferSize);
if (contentLength > 0)
{
position += bytesRead;
int percentage = (int)(position * 100 / contentLength);
if (percentage != storedPercentage)
{
progress?.Report(percentage);
storedPercentage = percentage;
}
}
}
}
}
控制台输出
File: [1.8 TO 1.16] Ultra Cosmetics [OPENSOURCE & FREE!!]#10905.jar
Content-Length: 1692542 bytes
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 73 72 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
Done.
文件下载成功。
与在浏览器中下载的 byte-by-byte 相比。文件相同。
我尝试下载一个 URL 的文件 returns 一个 307 重定向代码。
我尝试使用 WebClient.DownloadFile
方法,但它似乎不遵循所请求站点的重定向。我通过搜索这个问题找到的东西要么说它应该工作(Microsoft 文档)要么没有真正回答我的问题:WebClient Does not automatically redirect
我的第一个问题是为什么它不遵循重定向,即使它使用的 HttpWebRequest AllowAutoRedirect=true
?
我的第二个问题是如何最好地实现使用自动重定向下载文件的功能。
我使用的示例 URL 是:https://api.spiget.org/v2/resources/10905/download
但是这个 URL 并不总是重定向,我猜这取决于一些内部 API 状态。
这是一个简单的例子 HttpClient
.NET Core 3.1 控制台应用程序(UPD: 添加了进度报告)
class Program
{
private static readonly HttpClient client = new HttpClient(new HttpClientHandler() { AllowAutoRedirect = true });
static async Task Main(string[] args)
{
try
{
IProgress<int> progress = new Progress<int>(p =>
{
Console.Write(p + " ");
});
await DownloadAndSaveFileAsync("https://api.spiget.org/v2/resources/10905/download", progress);
Console.WriteLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine("Done.");
Console.ReadKey();
}
private static async Task DownloadAndSaveFileAsync(string url, IProgress<int> progress)
{
using HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
response.EnsureSuccessStatusCode(); // throw if not success
string fileName = response.Content.Headers.ContentDisposition?.FileName ?? throw new Exception("Nothing to download");
fileName = fileName.Trim('\"'); // remove quotes
long contentLength = response.Content.Headers.ContentLength ?? 0;
Console.WriteLine("File: {0}", fileName);
Console.WriteLine("Content-Length: {0} bytes", contentLength);
using Stream responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
using FileStream fileStream = File.Create(fileName);
int bufferSize = 65536;
byte[] buffer = new byte[bufferSize];
int bytesRead;
long position = 0;
int storedPercentage = -1;
while ((bytesRead = await responseStream.ReadAsync(buffer, 0, bufferSize)) > 0)
{
await fileStream.WriteAsync(buffer, 0, bufferSize);
if (contentLength > 0)
{
position += bytesRead;
int percentage = (int)(position * 100 / contentLength);
if (percentage != storedPercentage)
{
progress?.Report(percentage);
storedPercentage = percentage;
}
}
}
}
}
控制台输出
File: [1.8 TO 1.16] Ultra Cosmetics [OPENSOURCE & FREE!!]#10905.jar
Content-Length: 1692542 bytes
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 73 72 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
Done.
文件下载成功。
与在浏览器中下载的 byte-by-byte 相比。文件相同。