Альтернатива реализации URI .NET? - PullRequest
8 голосов
/ 10 февраля 2009

У меня проблема с реализацией URI .NET. Кажется, что если схема "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 голосов
/ 10 февраля 2009

Ну, проблема не в том, что я не могу создать FTP-соединение, а в том, что URI не анализируются в соответствии с RFC 2396.

Что я на самом деле намеревался сделать, так это создать фабрику, которая предоставляет реализации универсального интерфейса передачи файлов (содержащего методы get и put) на основе заданного URI соединения. URI определяет протокол, информацию о пользователе, хост и путь, и любые свойства, которые необходимо передать, должны быть переданы через часть запроса URI (например, параметр пассивного режима для соединения FTP).

Однако это оказалось трудным с использованием реализации .NET Uri, поскольку кажется, что он анализирует часть запроса URI по-разному в зависимости от схемы.

Так что я надеялся, что кто-то знает обходной путь к этому или альтернативу, казалось бы, испорченной реализации .NET Uri. Было бы неплохо узнать, прежде чем тратить часы на реализацию моего собственного.

2 голосов
/ 24 мая 2011

Некоторое время я боролся с той же проблемой. При попытке заменить существующий UriParser для схемы «ftp» с помощью UriParser.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 будет иметь строку запроса, которая, как и следовало ожидать, вместо параметра Path.

входит в параметр Query
2 голосов
/ 10 февраля 2009

Вы должны использовать классы FtpWebRequest и FtpWebResponse , если у вас нет особых причин не делать этого.

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

1 голос
/ 10 февраля 2009

Вы должны использовать специальный класс для протокола FTP, например FtpWebRequest, который имеет свойство Uri, например RequestUri.

Вам следует поискать в этих классах анализатор Uri, я думаю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...