2009-02-10 12 views
8

Tengo un problema con la implementación URI de .NET. Parece que si el esquema es "ftp", la parte de la consulta no se analiza como una consulta, sino como parte de la ruta en su lugar.¿Alternativa a la implementación URI de .NET?

Tome el siguiente código de ejemplo:

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" 

Me parece que la clase Uri analiza erróneamente la parte de consulta como parte de la ruta. Sin embargo cambiar el esquema de HTTP, el resultado es el esperado:

Uri testuri = new Uri("http://user:[email protected]/?passive=true"); 
Console.WriteLine(testuri.Query); // Outputs "?passive=true" 
Console.WriteLine(testuri.AbsolutePath); // Outputs "/" 

¿Alguien tiene una solución para esto, o sabe de una clase Uri alternativa que funciona como se esperaba?

Respuesta

4

Bueno, el problema no es que no soy capaz de crear una conexión FTP, pero que el URI de que no se analizan accoding a RFC 2396.

Lo que en realidad la intención de hacer fue crear una fábrica que proporciona implementaciones de una interfaz genérica de transferencia de archivos (que contiene los métodos get y put), basada en un URI de conexión determinado. El URI define el protocolo, la información del usuario, el host y la ruta, y las propiedades que deben pasarse deben pasarse a través de la parte de consulta del URI (como la opción del modo pasivo para la conexión FTP).

Sin embargo, esto resultó difícil usando la implementación .RI de URI, ya que parece analizar la parte de consulta de URI de forma diferente en función del esquema.

Así que esperaba que alguien supiera una solución a esto, o una alternativa a la implementación de URI de .NET aparentemente descompuesta. Sería bueno saberlo antes de pasar horas implementando el mío.

1

Tienes que usar una clase específica para el protocolo FTP como FtpWebRequest que tiene una propiedad Uri como RequestUri.

Debe buscar en esas clases para un analizador de Uri, creo.

2

Debe utilizar las clases FtpWebRequest y a menos que tenga un motivo específico para no hacerlo.

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

He estado luchando con el mismo problema por un tiempo. Intentar reemplazar el UriParser existente por el esquema "ftp" utilizando UriParser.Register arroja un InvalidOperationException porque el esquema ya está registrado.

La solución que he encontrado implica el uso de la reflexión para modificar el analizador de ftp existente para que permita la cadena de consulta. Esto se basa en una solución alternativa al 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); 
    } 
} 

Run que alguna parte de su inicialización, y su ftp Uris tendrá la cadena de consulta entrar en el parámetro Query, como era de esperar, en lugar de Path.