WebRequest实现文件下载的一个RFC规范问题

来源:互联网 发布:淘宝客退款佣金怎么办 编辑:程序博客网 时间:2024/05/17 05:54

前几天写一个C#的文件下载代码,实现起来也是非常容易,.net编程就是方便简洁

            WebRequest req = WebRequest.Create(url);            WebResponse pos = req.GetResponse();            long totalbytes = pos.ContentLength;            Stream s = pos.GetResponseStream();            FileStream fs = new FileStream(savefullpath, FileMode.OpenOrCreate, FileAccess.Write);            byte[] buffer = new byte[1024];            int bytesRead = s.Read(buffer, 0, buffer.Length);            long donebytes = 0;            while (bytesRead > 0)            {                fs.Write(buffer, 0, bytesRead);                bytesRead = s.Read(buffer, 0, buffer.Length);                if (progress != null)                {                    donebytes += bytesRead;                    progress(donebytes, totalbytes);                }            }            fs.Close();            s.Close();            pos.Close();
首先创建一个WebRequest对象,url则是下载文件的链接,获取响应的数据流Stream,然后打开本地文件将传输数据写入文件。

可是我发现下面两种下载链接程序会下载失败

http://localhost.com/file..name/a.tar  (链接中间有两个及两个以上点号)

http://localhost.com/filename/a.tar.   (链接结束处为点号)

通过WebRequest.Create函数处理后链接会发生变化为

http://localhost.com/filename/a.tar

http://localhost.com/filename/a.tar

这是不是webrequest的bug呢,我试了试HttpWebRequest,也是出现同样的错误,url会发生变化。

后来查阅一些网上的资料,发现上面出错的两类下载链接不符合rfc的某个uri资源标准的规范,微软的开发人员就自动帮我们处理了链接的“错误”,他们也太自作聪明了,呵呵。

要让程序不修改url,可以在创建webrequest对象之前写下下面的代码,通过设置一些标志位可以防止url被修改。

            MethodInfo getSyntax = typeof(UriParser).GetMethod("GetSyntax", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);            FieldInfo flagsField = typeof(UriParser).GetField("m_Flags", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);            if (getSyntax != null && flagsField != null)            {                foreach (string scheme in new[] { "http", "https" })                {                    UriParser parser = (UriParser)getSyntax.Invoke(null, new object[] { scheme });                    if (parser != null)                    {                        int flagsValue = (int)flagsField.GetValue(parser);                        // Clear the CanonicalizeAsFilePath attribute                        if ((flagsValue & 0x1000000) != 0)                            flagsField.SetValue(parser, flagsValue & ~0x1000000);                    }                }            }
请参考解决方案出处:http://stackoverflow.com/questions/856885/httpwebrequest-to-url-with-dot-at-the-end