Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTTP Range: bytes with WebClient C#

Tags:

c#

http

webclient

I am trying to resume file download.

I use the below code to successfully download the file I need.

    downlaodfile = new WebClient();
  // downlaodfile.Headers.Add("Range", "bytes=0-600000");
downlaodfile.DownloadFileAsync(new Uri(video.DownloadUrl), @"C:\Videofile.pm4");

The problem start when I uncomment the bellow line I get 0 bytes downloaded

 downlaodfile.Headers.Add("Range", "bytes=0-600000");

What is the right way to resume with WebClient class?

like image 293
Evgeni Tanchev Avatar asked Apr 24 '26 13:04

Evgeni Tanchev


1 Answers

Your code doesn't work because you cannot set the Range header the way you are trying to set it. To verify that simply subscribe to the DownloadFileCompleted event and dump the error:

downlaodfile.DownloadFileCompleted += (sender, e) =>
{
    Console.WriteLine(e.Error);
};

You will get this printed:

System.Net.WebException: An exception occurred during a WebClient request. ---> System.ArgumentException: The 'Range' header must be modified using the appropriate property or method.
Parameter name: name
   at System.Net.WebHeaderCollection.ThrowOnRestrictedHeader(String headerName)
   at System.Net.WebHeaderCollection.Add(String name, String value)
   at System.Net.HttpWebRequest.set_Headers(WebHeaderCollection value)
   at System.Net.WebClient.CopyHeadersTo(WebRequest request)
   at System.Net.WebClient.GetWebRequest(Uri address)
   at System.Net.WebClient.DownloadFileAsync(Uri address, String fileName, Object userToken)
   --- End of inner exception stack trace ---

OK, so you might need a custom WebClient:

public class WebClientEx : WebClient
{
    private readonly long from;
    private readonly long to;

    public WebClientEx(long from, long to)
    {
        this.from = from;
        this.to = to;
    }

    protected override WebRequest GetWebRequest(Uri address)
    {
        var request = (HttpWebRequest)base.GetWebRequest(address);
        request.AddRange(this.from, this.to);
        return request;
    }
}

that you could use like this:

downlaodfile = new WebClientEx(0, 600000);
downlaodfile.DownloadFileAsync(new Uri(video.DownloadUrl), @"C:\Videofile.pm4");

or simply use the HttpWebRequest class instead of a WebClient:

var request = (HttpWebRequest)WebRequest.Create(video.DownloadUrl);
request.AddRange(0, 600000);
using (var response = await request.GetResponseAsync())
using (var stream = response.GetResponseStream())
using (var output = File.Create(@"C:\Videofile.pm4"))
{
    await stream.CopyToAsync(output);
}

or if you prefer with an HttpClient:

var client = new HttpClient();
client.DefaultRequestHeaders.Range = new RangeHeaderValue(0, 600000);
using (var stream = await client.GetStreamAsync(video.DownloadUrl))
using (var output = File.Create(@"C:\Videofile.pm4"))
{
    await stream.CopyToAsync(output);
}
like image 149
Darin Dimitrov Avatar answered Apr 27 '26 03:04

Darin Dimitrov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!