为什么在 C# 中使用 HttpClient 找到服务器 returns HTTP 302 时无法下载文件?
Why can't I download a file when the server returns HTTP 302 Found using HttpClient in C#?
我在下载一个最终在 302 之后返回的文件时遇到问题。
假设我有一个像这样的 URL:https://myhost/export/myfile.php。当我在浏览器中导航到此 URL 时,文件会下载。
但是,我想使用 C# 下载文件。
这是我尝试过的方法,使用 HttpClient
,但不起作用:
var uri = "https://myhost/export/myfile.php";
var requestMessage = new HttpRequestMessage(HttpMethod.Get, uri);
var handler = new HttpClientHandler();
handler.AllowAutoRedirect = true;
using (var client = new HttpClient(handler))
{
var response = await client.SendAsync(requestMessage);
if (response.IsSuccessStatusCode)
{
/// it never reach here because 302 is not sucess status code
}
}
我也试过使用 WebClient
:
var url = "https://myhost/export/myfile.php";
using (var webclient = new WebClient())
{
var response = await _webClient.DownloadDataTaskAsync(url); // throws an exception regarding HTTP status being 302 Found
string download = Encoding.ASCII.GetString(response);
}
如何下载重定向后返回的文件?
------------问题解决------------
在@Ermiya Eskandary 的支持下,我终于找到了根本原因。此请求缺少身份验证所需的 header 名称 'Cookie'(我将其误认为是 cookie => 错误的请求配置)。感谢上帝派这个人来帮助我。
状态代码为 302 的 HTTP 响应表示请求的信息位于响应的 Location
header 中指定的 URI(本质上是重定向)。
考虑到您已设置 HttpClientHandler.AllowAutoRedirect
,处理程序将自动遵循 HTTP 重定向 header,直到您收到没有指示重定向的状态代码的响应。
我也不怀疑服务器将您重定向超过 50 次,这是 HttpClientHandler.MaxAutomaticRedirections
的默认值,因此只留下一件事。
无论响应完成后服务器实际上出于何种原因返回失败状态代码,或者如果没有,需要注意的 重要 注意事项是,除非您正在使用 .NET Framework(而不是 .NET Core 等),HttpClient
will not follow redirections from a secure HTTPS endpoint to an insecure HTTP endpoint.
出于安全原因,您不能覆盖自动重定向 dis-allowing HTTPS -> HTTP 但是,如果您 必须 ,请自行解析 Location
header直到重定向完成。
这应该有效:
var uri = "https://myhost/export/myfile.php";
var initialRequestMessage = new HttpRequestMessage(HttpMethod.Get, URI);
initialRequestMessage.Headers.Add("Cookie", "PHPSESSID=...");
using (var client = new HttpClient())
{
var response = await client.SendAsync(initialRequestMessage);
while (response.StatusCode == HttpStatusCode.Found)
{
Uri redirectedUri = response.Headers.Location;
var requestMessage = new HttpRequestMessage(HttpMethod.Get, redirectedUri);
response = await client.SendAsync(requestMessage);
}
// response is successful or unsuccessful but will not be a redirect
Console.WriteLine(response.StatusCode);
}
我在下载一个最终在 302 之后返回的文件时遇到问题。
假设我有一个像这样的 URL:https://myhost/export/myfile.php。当我在浏览器中导航到此 URL 时,文件会下载。
但是,我想使用 C# 下载文件。
这是我尝试过的方法,使用 HttpClient
,但不起作用:
var uri = "https://myhost/export/myfile.php";
var requestMessage = new HttpRequestMessage(HttpMethod.Get, uri);
var handler = new HttpClientHandler();
handler.AllowAutoRedirect = true;
using (var client = new HttpClient(handler))
{
var response = await client.SendAsync(requestMessage);
if (response.IsSuccessStatusCode)
{
/// it never reach here because 302 is not sucess status code
}
}
我也试过使用 WebClient
:
var url = "https://myhost/export/myfile.php";
using (var webclient = new WebClient())
{
var response = await _webClient.DownloadDataTaskAsync(url); // throws an exception regarding HTTP status being 302 Found
string download = Encoding.ASCII.GetString(response);
}
如何下载重定向后返回的文件?
------------问题解决------------ 在@Ermiya Eskandary 的支持下,我终于找到了根本原因。此请求缺少身份验证所需的 header 名称 'Cookie'(我将其误认为是 cookie => 错误的请求配置)。感谢上帝派这个人来帮助我。
状态代码为 302 的 HTTP 响应表示请求的信息位于响应的 Location
header 中指定的 URI(本质上是重定向)。
考虑到您已设置 HttpClientHandler.AllowAutoRedirect
,处理程序将自动遵循 HTTP 重定向 header,直到您收到没有指示重定向的状态代码的响应。
我也不怀疑服务器将您重定向超过 50 次,这是 HttpClientHandler.MaxAutomaticRedirections
的默认值,因此只留下一件事。
无论响应完成后服务器实际上出于何种原因返回失败状态代码,或者如果没有,需要注意的 重要 注意事项是,除非您正在使用 .NET Framework(而不是 .NET Core 等),HttpClient
will not follow redirections from a secure HTTPS endpoint to an insecure HTTP endpoint.
出于安全原因,您不能覆盖自动重定向 dis-allowing HTTPS -> HTTP 但是,如果您 必须 ,请自行解析 Location
header直到重定向完成。
这应该有效:
var uri = "https://myhost/export/myfile.php";
var initialRequestMessage = new HttpRequestMessage(HttpMethod.Get, URI);
initialRequestMessage.Headers.Add("Cookie", "PHPSESSID=...");
using (var client = new HttpClient())
{
var response = await client.SendAsync(initialRequestMessage);
while (response.StatusCode == HttpStatusCode.Found)
{
Uri redirectedUri = response.Headers.Location;
var requestMessage = new HttpRequestMessage(HttpMethod.Get, redirectedUri);
response = await client.SendAsync(requestMessage);
}
// response is successful or unsuccessful but will not be a redirect
Console.WriteLine(response.StatusCode);
}