当服务器返回 HTTP 302 Found using HttpClient in C# 为啥我不能下载文件?

Posted

技术标签:

【中文标题】当服务器返回 HTTP 302 Found using HttpClient in C# 为啥我不能下载文件?【英文标题】:Why can't I download a file when the server returns HTTP 302 Found using HttpClient in C#?当服务器返回 HTTP 302 Found using HttpClient in C# 为什么我不能下载文件? 【发布时间】:2021-11-26 15:29:24 【问题描述】:

我在下载文件时遇到问题,该文件最终在 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 的支持下,我终于找到了根本原因。此请求缺少身份验证所需的标头名称“Cookie”(我用 cookie => 错误的请求配置误解了它)。感谢上帝派这个人来帮助我。

【问题讨论】:

var response = await _client.SendAsync(requestMessage); 之后的状态码是什么 - 你100% 确定是 302 吗? 您被重定向到的 URL 是什么?对于 .NET Core 1.0、1.1、2.0,它不会遵循从 HTTPS 到 HTTP 的重定向 - 请参阅 docs.microsoft.com/en-us/dotnet/api/… 是的,它是 302,我使用的是 netcore 3.1 【参考方案1】:

状态码为302 的HTTP 响应表明请求的信息位于响应的Location 标头中指定的URI(本质上是重定向)。

考虑到您已设置 HttpClientHandler.AllowAutoRedirect,处理程序将自动遵循 HTTP 重定向标头,直到您到达没有指示重定向的状态代码的响应。

我也不怀疑服务器将您重定向超过 50 次,这是 HttpClientHandler.MaxAutomaticRedirections 的默认值,因此只剩下一件事。

一旦响应完成,无论出于何种原因,服务器实际上都会返回一个失败的状态代码,或者如果它不是,一个需要注意的重要注意事项是,除非您使用 . NET Framework(而不是 .NET Core 等),HttpClient will not follow redirections from a secure HTTPS endpoint to an insecure HTTP endpoint

出于安全原因,您不能覆盖禁止 HTTPS -> HTTP 的自动重定向,但是如果您必须,请自行解析 Location 标头,直到重定向完成。

这应该可行:

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);

【讨论】:

仍然没有解决我的问题,'response.Headers.Location' 与原始 url 具有相同的 uri。但我对你的回答印象深刻,谢谢你的帮助。 @TôĐôngHồ 那么资源是否只是不断地重定向到自身?它真的会在任何地方结束吗?可以从浏览器下载吗?这听起来像是服务器问题。 我把链接放在浏览器上,回车,它立即下载。当我使用邮递员时,它也返回 302。但是,当我打开“自动遵循重定向”设置时,它会顺利获得响应。 (x_x) 你能分享一下链接吗?如果它返回 302,则上面的代码将 100% 工作,除非服务器需要其他标头/用户代理。上面的代码可以工作(考虑到你还没有完成handler.AllowAutoRedirect = true;)——上面的代码应该替换你所有的代码。 @TôĐôngHồ 上面的代码要么陷入无限循环,要么最终退出while循环——它会退出while循环吗?尝试更新的答案,让我知道输出

以上是关于当服务器返回 HTTP 302 Found using HttpClient in C# 为啥我不能下载文件?的主要内容,如果未能解决你的问题,请参考以下文章

接口返回302 Found

FreeMarker 模板加载器返回 302 Found

http 301和302的区别

基于 Django 类的视图:发布表单数据返回 302 Found 状态码

302 Found nginx是啥意思

php curl抓取网页内容在服务器上报302Found,怎么解决