How to specify range >2GB for HttpWebRequest in .N

2019-02-19 00:46发布

问题:

I'm building this class to download files in parts/sections/segments. In .NET 4.0, I can use this code to specify the range to download from

long startPos = int.MaxValue+1;
HttpWebRequest.AddRange(startPos);

and it works because there is a long overload for the AddRange method.

When I looked up the .NET 3.5 version, I realised the AddRange() method allows using int only.

The possible workaround would be using the AddRange(string, int) or AddRange(string, int, int) methods. Since the class will have to work in .NET 3.5, I'll have to go with the string specification but unfortunately I can't seem to find any sample code that shows how to specify ranges using this procedure in .NET 3.5. Can anyone show be how to do this?

Thanks.

Update

As the first code sample I wrote shows, I would like to specify a range of type long instead of int. Using type int allows requesting for byte ranges only up to 2GB but long allows requesting for byte ranges beyong 2GB.

The question therefore is: How do I specify byte ranges of 2GB or higher on HttpWebRequest in .NET 3.5?

回答1:

This is the code by Mutant_Fruit copied from WebRequest.AddRange - what about files > 2gb? showing how to to add a range specifier longer than 2GB to an HttpWebRequest.

MethodInfo method = typeof(WebHeaderCollection).GetMethod
                        ("AddWithoutValidate", BindingFlags.Instance | BindingFlags.NonPublic);

HttpWebRequest request = (HttpWebRequest) WebRequest.Create ("http://www.example.com/file.exe");

long start = int32.MaxValue;
long end = int32.MaxValue +  100000;

string key = "Range";
string val = string.Format ("bytes={0}-{1}", start, end);

method.Invoke (request.Headers, new object[] { key, val });

I wrote this extension method for it.

#region HttpWebRequest.AddRange(long)
static MethodInfo httpWebRequestAddRangeHelper = typeof(WebHeaderCollection).GetMethod
                                        ("AddWithoutValidate", BindingFlags.Instance | BindingFlags.NonPublic);
/// <summary>
/// Adds a byte range header to a request for a specific range from the beginning or end of the requested data.
/// </summary>
/// <param name="request">The <see cref="System.Web.HttpWebRequest"/> to add the range specifier to.</param>
/// <param name="start">The starting or ending point of the range.</param>
public static void AddRange(this HttpWebRequest request, long start) { request.AddRange(start, -1L); }

/// <summary>Adds a byte range header to the request for a specified range.</summary>
/// <param name="request">The <see cref="System.Web.HttpWebRequest"/> to add the range specifier to.</param>
/// <param name="start">The position at which to start sending data.</param>
/// <param name="end">The position at which to stop sending data.</param>
public static void AddRange(this HttpWebRequest request, long start, long end)
{
    if (request == null) throw new ArgumentNullException("request");
    if (start < 0) throw new ArgumentOutOfRangeException("start", "Starting byte cannot be less than 0.");
    if (end < start) end = -1;

    string key = "Range";
    string val = string.Format("bytes={0}-{1}", start, end == -1 ? "" : end.ToString());

    httpWebRequestAddRangeHelper.Invoke(request.Headers, new object[] { key, val });
}
#endregion

The extension methods above need the following using directives

using System.Reflection;
using System.Net;

And there is no need to use this this extension method in .NET 4 because there are two overloads of the AddRange method that accept int64 (long) as parameters.



回答2:

I believe the documentation gives some insight into that:

An example of a Range header in an HTTP protocol request that requests the first 100 bytes would be would be the following:

Range: bytes=-99\r\n\r\n

For this example, the rangeSpecifier parameter would be specified as "bytes" and the range parameter would be -99.

Then there is also this from Wikipedia:

Range
Request only part of an entity. Bytes are numbered from 0.
Range: bytes=500-999

So the code that you would result on the example above is

HttpWebRequest.AddRange("bytes", 500, 999);


回答3:

If I understand you correctly, you do not have enough int and long. But operator overloading only int?

Use headers.

httpWebRequest.Headers.Add("Range", "bytes=500-999");


回答4:

Since .NET 4, HttpWebRequest.AddRange() supports long: http://msdn.microsoft.com/en-us/library/dd992108.aspx