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 回答 4

4

好吧,问题不在于我无法创建 FTP 连接,而是 URI 没有根据 RFC 2396 进行解析。

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

然而,使用 .NET Uri 实现证明这很困难,因为它似乎根据架构以不同的方式解析 URI 的查询部分。

所以我希望有人知道解决这个问题的方法,或者是看似损坏的 .NET Uri 实现的替代方法。在花几个小时实施我自己的之前知道会很高兴。

于 2009-02-10T14:01:08.460 回答
3

我一直在为同样的问题苦苦挣扎一段时间。尝试使用“ftp”方案替换现有的 UriParserUriParser.Register会抛出一个错误,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 Uris 将使查询字符串进入Query参数,正如您所期望的那样,而不是Path.

于 2011-05-24T16:44:47.510 回答
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

于 2009-02-10T11:44:39.897 回答
1

您必须为 FTP 协议使用特定类,例如 FtpWebRequest,它具有像 RequestUri 这样的 Uri 属性。

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

于 2009-02-10T11:27:21.187 回答