Why can't I download a file when the server returns HTTP 302 Found using HttpClient in C#?

Viewed 1044

I have issues downloading a file which is eventually returned after a 302.

Suppose I have a URL like this: https://myhost/export/myfile.php. When I navigate to this URL in my browser, the file downloads.

However, I want to download the file using C#.

Here's what I've tried, using HttpClient, which doesn't work:

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
    }
}

I've also tried using 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);
}

How can I download a file which is returned after redirects?

---------Problem solved ------------ After @Ermiya Eskandary 's support, I finally found the root cause. This request missing a header name 'Cookie' that needed for authentication (which I misunderstanding it with cookie => wrong configuration for request). Thank god send this man to help me out.

1 Answers

An HTTP response with status code 302 indicates that the requested information is located at the URI specified in the Location header of the response (a redirect essentially).

Considering you have set HttpClientHandler.AllowAutoRedirect, the handler will automatically follow HTTP redirections headers until you reach a response that doesn't have a status code indicating a redirection.

I also don't suspect that the server is redirecting you more than 50 times, which is the default value for HttpClientHandler.MaxAutomaticRedirections so that only leaves one thing.

Either the server is actually returning a failing status code for whatever reason once the response is complete or if it isn't, an important note to be aware of is that unless you are using the .NET Framework (and not .NET Core etc.), HttpClient will not follow redirections from a secure HTTPS endpoint to an insecure HTTP endpoint.

You cannot override automatic redirection dis-allowing HTTPS -> HTTP for security reasons however if you must, parse the Location header yourself until the redirection is complete.

This should work:

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