2009-02-10 58 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參數,如你所願。