2009-02-10 70 views
8

我有一个.NET的Uri实现的问题。看起来,如果该方案是“ftp”,查询部分不会被解析为查询,而是作为路径的一部分。替代.NET的Uri实现?

看看下面的代码,例如:

Uri testuri = new Uri("ftp://user:[email protected]/?passive=true"); 
Console.WriteLine(testuri.Query); // Outputs an empty string 
Console.WriteLine(testuri.AbsolutePath); // Outputs "/%3Fpassive=true" 

在我看来,该Uri类错误地分析查询部分为路径的一部分。然而改变为http方案,如预期的结果:

Uri testuri = new Uri("http://user:[email protected]/?passive=true"); 
Console.WriteLine(testuri.Query); // Outputs "?passive=true" 
Console.WriteLine(testuri.AbsolutePath); // Outputs "/" 

有没有人有一个解决的办法,或者知道一个替代Uri类如预期那样工作的?

回答

4

好了,问题不在于我无法建立一个FTP连接,但URI的不解析accoding到RFC 2396

我确实打算这样做是创建一个工厂,该工厂基于给定的连接URI提供通用文件传输接口(包含get和put方法)的实现。 URI定义了协议,用户信息,主机和路径,并且需要传递的任何属性都应通过URI的查询部分(例如FTP连接的被动模式选项)传递。

然而,使用.NET Uri实现证明这很困难,因为它似乎基于模式来分析URI的Query部分是不同的。

所以我希望有人知道这个解决方法,或者看似破碎的.NET Uri实现的替代方案。在花费数小时实施我自己的工作之前,我会很高兴知道。

1

您必须使用FTP协议的特定类,如FtpWebRequest,其具有Uri属性(如RequestUri)。

你应该在thoses类中搜索我认为的Uri解析器。

2

除非您有特定的原因,否则您应该使用FtpWebRequestFtpWebResponse类。

FtpWebRequest.fwr = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://uri")); 
fwr.ftpRequest.Method = WebRequestMethods.Ftp.UploadFile; 
fwr.ftpRequest.Credentials = new NetworkCredential("user", "pass"); 


FileInfo ff = new FileInfo("localpath"); 
byte[] fileContents = new byte[ff.Length]; 

using (FileStream fr = ff.OpenRead()) 
{ 
    fr.Read(fileContents, 0, Convert.ToInt32(ff.Length)); 
} 

using (Stream writer = fwr.GetRequestStream()) 
{ 
    writer.Write(fileContents, 0, fileContents.Length); 
} 

FtpWebResponse frp = (FtpWebResponse)fwr.GetResponse(); 
Response.Write(frp.ftpResponse.StatusDescription); 

Ref1Ref2

2

我一直在同一个问题挣扎了一段时间。试图用UriParser.Register替换现有的“ftp”方案的UriParser将抛出InvalidOperationException,因为该方案已经注册。

我提出的解决方案涉及使用反射修改现有的ftp解析器,以便它允许查询字符串。这是基于到another UriParser bug的解决方法。

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) 
{ 
    UriParser parser = (UriParser)getSyntax.Invoke(null, new object[] { "ftp"}); 
    if (parser != null) 
    { 
     int flagsValue = (int)flagsField.GetValue(parser); 

     // Set the MayHaveQuery attribute 
     int MayHaveQuery = 0x20; 
     if ((flagsValue & MayHaveQuery) == 0) flagsField.SetValue(parser, flagsValue | MayHaveQuery); 
    } 
} 

运行,而不是Path,在你的初始化,您的FTP地方尤里斯将查询字符串进入Query参数,如你所愿。