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 });
You need to call the protected method of the WebHeaderCollection class so you can add the "Range" header without being forced to go through the broken HttpWebRequestAddRange method. I tried about a half dozen more legitimate methods, but the API is so locked down that it was impossible.
For example, HttpWebRequest.Headers is a get/set property, but if you set a new collection, it checks to make sure "Range" isn't there, and then just copies the keys from your new collection into it's internal one and ignores the collection you just gave it. What this means is that:
CustomCollection c = new CustomCollection ();
request.Headers = c;
Console.WriteLine (request.Headers == c);
prints false.
Ouch.
Anyway, the hack works. If you need 64bit indices when downloading files via HttpWebRequest, here's your guaranteed working hack, on both Mono and MS.NET.
6 comments:
Method.Invoke might prove to be a little slow.
@GrayShade:
Compared to the time taken to download a few MB of data once the webrequest has been created, Method.Invoke could be 1000 times slower and I'd still not noticee difference ;)
Is there an open issue on MS Connect about this? :)
If yes, it would be nice to post the link. If not, it would be nice to file it.
Couldn't you just inherit from the WebHeaderCollection class and add a public constructor which called the protected constructor? It should be less messy that way.
@Ryan:
Nope. If you read the last two paragraphs of my blogpost, i actually covered that issue. This hack is the *only* safe way around the bug in the framework design.
The only other option available is to write a proxying class. The idea of the proxy is this:
1) Create a WebRequest to "www.url.com".
2) Fill in any settings/headers you require into the WebRequest.
3) When you want to call WebRequest.GetResponse, instead create a socket which listens at 127.0.0.1:PORT and then make your webrequest go to 127.0.0.1:PORT.4
4) Read all the data from the socket.
5) Add on the "Range" header
6) Create another socket which contacts "www.url.com" and forward on the header data
7) Proxy data to/from the remote server through this socket
Obviously enough, this method is definitely less efficient, but it will work 100% of the time and doesn't involve nasty reflection hacks.
However, i think using reflection to call the protected member is perfectly OK as that is part of the public API and will not change. Calling a private or internal member would definitely be a no-go though.
It was not long cheap wow goldbefore some one knocked atwow gold cheap wow gold for salethe house-door and called, open the door, dear children, your mother is here, and has brought something back with her for each of you. But the little wow goldkids knew that it was the wolf, by the rough voice. We will wow power leveling not open the door, cried they, you are not our mother. She has a soft, pleasant voice, but your voice is rough, you are the wolf.
Then the wolf went World Of Warcraft Goldaway to a shopkeeper and bought himself a great cheapest wow goldlump of chalk, ate this and made gold4power.com his voice soft with it. The he came back, knocked at the door of the house, and world of warcraft gold salecalled, open the door, dear children, your mother is here and Cheapest Wow Goldhas brought something back with her for each of you.
Post a Comment