To download a file with HttpClient
you can do:
// Is better to not initialize a new HttpClient each time you make a request,
// it could cause socket exhaustion
private static HttpClient _httpClient = new HttpClient()
{
Timeout = TimeSpan.FromSeconds(5)
};
public async Task<byte[]> GetFile(string fileUrl)
{
using (var httpResponse = await _httpClient.GetAsync(fileUrl))
{
// Throws an exception if response status code isn't 200
httpResponse.EnsureSuccessStatusCode();
return await httpResponse.Content.ReadAsByteArrayAsync();
}
}
For more details about socket exhaustion with HttpClient
As you see, to define a timeout for the Http
call you should set a timeout while creating a new HttpClient
.
To implement a retry policy for the previous code, I would install Polly NuGet package and then:
public async Task<byte[]> GetFile(string fileUrl)
{
return await Policy
.Handle<TaskCanceledException>() // The exception thrown by HttpClient when goes in timeout
.WaitAndRetryAsync(retryCount: 3, sleepDurationProvider: i => TimeSpan.FromMilliseconds(300))
.ExecuteAsync(async () =>
{
using (var httpResponse = await _httpClient.GetAsync(fileUrl))
{
// Throws an exception if response status code isn't 200
httpResponse.EnsureSuccessStatusCode();
return await httpResponse.Content.ReadAsByteArrayAsync();
}
});
}
In this case I defined a retry of 3 times with an interval of 300 milliseconds between each tentative. Also note that I didn't defined the retry for every kind of Exception
, because if - for example - you put an invalid URL
, retrying is nonsense.
At the end, if you want to save that byte array to a file, you can just do:
File.WriteAllBytes(@"MyPath\file.extension", byteArray);