.NET的Uri实现有哪些替代方案?

9
我对.NET的Uri实现存在问题。似乎如果方案是“ftp”,查询部分不会被解析为查询,而是被解析为路径的一部分。
以以下代码为例:
Uri testuri = new Uri("ftp://user:pass@localhost/?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:pass@localhost/?passive=true");
Console.WriteLine(testuri.Query); // Outputs "?passive=true"
Console.WriteLine(testuri.AbsolutePath); // Outputs "/"

有人有解决这个问题的方法吗?或者知道一个可以按预期工作的替代Uri类吗?

4个回答

4
好的,问题不在于我无法创建FTP连接,而是URI没有按照RFC 2396进行解析。我实际想做的是创建一个工厂,根据给定的连接URI提供通用文件传输接口的实现(包含获取和放置方法)。 URI定义协议、用户信息、主机和路径,并且应该通过URI的查询部分传递任何需要传递的属性(例如FTP连接的被动模式选项)。
然而,使用.NET Uri实现证明这很困难,因为它似乎基于架构以不同方式解析URI的查询部分。
因此,我希望有人知道解决此问题的方法,或者了解看起来有缺陷的.NET Uri实现的替代方案。在实现自己的功能之前知道这一点会很好。

为什么不检查URI是否以“ftp:”开头,然后将方案更改为类似于“x.generic:”的内容?您将从中获取查询。 - IS4

3
我已经为此问题苦苦挣扎了一段时间。尝试使用UriParser.Register替换“ftp”方案的现有UriParser会抛出InvalidOperationException,因为该方案已经注册。
我想到的解决方案涉及使用反射修改现有的ftp解析器,以便允许查询字符串。这是基于另一个UriParser错误的解决方法。
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);
    }
}

将其放在初始化中运行,您的FTP URI将使查询字符串进入Query参数,而不是Path,正如您所期望的那样。


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); 

参考链接1 参考链接2


1

你需要使用特定的FTP协议类,例如FtpWebRequest,该类具有像RequestUri这样的Uri属性。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接