简体   繁体   English

替代.NET的Uri实现?

[英]Alternative to .NET's Uri implementation?

I have a problem with the .NET's Uri implementation. 我有一个.NET的Uri实现的问题。 It seems that if the scheme is "ftp", the query part is not parsed as a Query, but as a part of the path instead. 似乎如果方案是“ftp”,则查询部分不会被解析为Query,而是作为路径的一部分进行解析。

Take the following code for example: 以下面的代码为例:

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"

It seems to me that the Uri class wrongfully parses the query part as a part of the path. 在我看来,Uri类错误地将查询部分解析为路径的一部分。 However changing the scheme to http, the result is as expected: 但是将方案更改为http,结果如预期:

Uri testuri = new Uri("http://user:pass@localhost/?passive=true");
Console.WriteLine(testuri.Query); // Outputs "?passive=true"
Console.WriteLine(testuri.AbsolutePath); // Outputs "/"

Does anyone have a solution to this, or know of an alternative Uri class that works as expected? 有没有人有这个解决方案,或知道一个按预期工作的替代Uri类?

Well, the problem is not that I am unable to create a FTP connection, but that URI's are not parsed accoding to RFC 2396. 好吧,问题不在于我无法创建FTP连接,而是根据RFC 2396解析了URI。

What I actually intended to do was to create a Factory that provides implementations of a generic File transfer interface (containing get and put methods), based on a given connection URI. 我实际上打算做的是创建一个Factory,它基于给定的连接URI提供通用文件传输接口(包含get和put方法)的实现。 The URI defines the protocol, user info, host and path, and any properties needed to be passed should be passed through the Query part of the URI (such as the Passive mode option for the FTP connection). URI定义协议,用户信息,主机和路径,并且需要传递的任何属性都应该通过URI的Query部分传递(例如FTP连接的被动模式选项)。

However this proved difficult using the .NET Uri implementation, because it seems to parse the Query part of URI's differently based on the schema. 然而,使用.NET Uri实现证明这很困难,因为它似乎根据模式不同地解析URI的Query部分。

So I was hoping that someone knew a workaround to this, or of an alternative to the seemingly broken .NET Uri implementation. 所以我希望有人知道这个的解决方法,或者替代看似破坏的.NET Uri实现。 Would be nice to know before spending hours implementing my own. 在花费数小时实现我自己之前会很高兴知道。

You should use the FtpWebRequest and FtpWebResponse classes unless you have a specific reason not to. 您应该使用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); 

Ref1 Ref2 Ref1 Ref2

I have been struggling with the same issue for a while. 我一直在努力解决同样的问题。 Attempting to replace the existing UriParser for the "ftp" scheme using UriParser.Register throws an InvalidOperationException because the scheme is already registered. 尝试使用UriParser.Register替换“ftp”方案的现有UriParser会抛出InvalidOperationException因为该方案已经注册。

The solution I have come up with involves using reflection to modify the existing ftp parser so that it allows the query string. 我提出的解决方案涉及使用反射来修改现有的ftp解析器,以便它允许查询字符串。 This is based on a workaround to another UriParser bug . 这是基于另一个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);
    }
}

Run that somewhere in your initialization, and your ftp Uris will have the query string go into the Query parameter, as you would expect, instead of Path . 在初始化的某个地方运行,你的ftp Uris将使查询字符串进入Query参数,正如您所期望的那样,而不是Path

You have to use a specific class for FTP protocol like FtpWebRequest that has a Uri property like RequestUri. 您必须使用特定类的FTP协议,如FtpWebRequest,它具有像RequestUri这样的Uri属性。

You should search in thoses classes for a Uri parser I think. 您应该在类中搜索我认为的Uri解析器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM