2008-10-02 80 views
20

¿Hay alguna manera de cargar un archivo en un servidor FTP cuando se encuentra detrás de un proxy HTTP?Carga de archivos FTP con HTTP Proxy

Parece que no se admite la carga de un archivo detrás de un Proxy HTTP utilizando .Net Webclient. (http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.proxy.aspx).

¿Si no hay una solución? Si no, ¿conoces una buena y gratuita biblioteca FTP que pueda usar?

Editar: Desafortunadamente, no tengo ningún proxy FTP para conectarme.

+0

¿Estás seguro de que su empresa no tiene un proxy FTP también? – VVS

+1

Tengo el mismo problema. ¿Encontraste una solución? –

+0

Y si lo hizo, ¿qué tipo de licencia era? Una distribución de fuente sería agradable. –

Respuesta

-5

Id realmente no veo la conexión entre un proxy http y la carga a un servidor ftp. Si usa la clase http proxy, eso es para acceder a los recursos http a través de un proxy http. ftp es otro protocolo y los proxies ftp usan un protocolo diferente.

+3

No olvide el método CONNECT de proxies HTTP. El método facilita la tunelización de conexiones TCP arbitrarias de salida. Por ejemplo, así es como funciona HTTPS a través de un proxy HTTP. – Alexander

9

En el modo FTP activo, el servidor inicia una conexión de datos con el cliente. Si el cliente está detrás de un proxy HTTP, obviamente esto no funcionará. En el modo FTP pasivo, el cliente inicia las conexiones de datos y de inicio. Como los proxies HTTP pueden tunelizar conexiones TCP salientes arbitrarias (utilizando el método CONNECT), debería ser posible acceder a un servidor FTP en modo pasivo a través de un proxy HTTP.

El FtpWebRequest parece ser compatible con el modo pasivo. Sin embargo, no entiendo por qué la descarga de archivos y las listas de directorios son compatibles, mientras que la carga de archivos, que también usa la misma conexión de datos, no lo es.

¿Ha confirmado que FtpWebRequest configurado para modo pasivo no funciona a través de un proxy HTTP a través del cual las listas de directorios/descarga de archivos funcionan bien?

+4

Este inconveniente está documentado: "Si el proxy especificado es un proxy HTTP, solo se admiten los comandos DownloadFile, ListDirectory y ListDirectoryDetails" - http://msdn.microsoft.com/en-us/library/system.net. ftpwebrequest.proxy.aspx –

5

mayoría de los proxies FTP hacer sus cosas en la conexión, por lo que si usted no tenía ningún proxy, haga lo siguiente:

  • servidor: myftpserver.com
  • usuario: Me
  • contraseña: pwd

usando un proxy FTP, que hace:

y que sólo funciona a partir de ahí. Estoy usando este DERECHO ESTE SEGUNDO (tratando de depurar algo) a través de un proxy Squid.

... pero como usted no tiene un proxy FTP ....

¿Tiene un proxy SOCKS? Eso podría funcionar, pero no sé si .NET puede hacerlo. De lo contrario, para ser sincero, ¡creo que estás atascado! FTP es un protocolo "extraño", cuando se compara con HTTP, ya que tiene un canal de control (puerto 21) y un canal de datos (o más de uno, en un puerto aleatorio), por lo que ir a través de proxies es ... divertido para ¡por decir lo menos!

+0

No tiene un proxy FTP. – VVS

+0

insecto, se perdió ese bit. Editando –

2

Si hay una manera de cargar un archivo a través de FTP sin C#, entonces también debería ser posible en C#. ¿Funciona la carga a través de un navegador o un cliente FTP?

La única biblioteca de FTP que más me gusta es .NET FTP Client library.

+0

¿Admite túneles a través de proxies HTTP? Eché un vistazo a la descripción general (http://sourceforge.net/docman/display_doc.php?docid=19518&group_id=92889), pero no pude encontrar ninguna referencia a los proxies. – Alexander

+0

Supongo que, si el cliente FTP anterior funciona bien en modo pasivo, entonces podría modificar fácilmente su código fuente para tunelizar las conexiones TCP (se trata de unas 20 líneas de código en Java). – Alexander

+0

@Alexander: Tengo que admitir que solo lo usé con un proxy FTP que puede usarse como un servidor FTP normal. – VVS

2

Como dice Alexander, los proxies HTTP pueden proxy de tráfico arbitrario. Lo que necesita es un Cliente FTP que tenga soporte para usar un Proxy HTTP. Alexander también tiene razón en que esto solo funcionaría en modo pasivo.

Mi empleador vende un cliente de FTP, pero es una herramienta de nivel empresarial que solo viene como parte de un sistema muy grande.

Estoy seguro de que hay otras disponibles que se adaptarían mejor a sus necesidades.

3

Una solución es intentar la implementación de Mono de FtpWebRequest. Eché un vistazo a su código fuente y parece que será fácil de modificar para que todas las conexiones (control y datos) se tunelicen a través de un proxy HTTP.

Establece una conexión TCP a su proxy HTTP en lugar del servidor FTP real. A continuación, envíe CONNECT myserver:21 HTTP/1.0 seguido de dos CRLF (CRLF = \ r \ n). Si el proxy necesita autenticación, debe usar HTTP/1.1 y también enviar un encabezado de autenticación proxy con las credenciales. Entonces necesitas leer la primera línea de la respuesta. Si comienza con "HTTP/1.0 200" o "HTTP/1.1 200", entonces usted (el resto del código) puede continuar usando la conexión como si estuviese conectado directamente al servidor FTP.

5

Nuestro Rebex FTP/SSL puede usar proxy HTTP. No es gratis, aunque ...

// initialize FTP client 
Ftp client = new Ftp(); 

// setup proxy details 
client.Proxy.ProxyType = FtpProxyType.HttpConnect; 
client.Proxy.Host = proxyHostname; 
client.Proxy.Port = proxyPort; 

// add proxy username and password when needed 
client.Proxy.UserName = proxyUsername; 
client.Proxy.Password = proxyPassword; 

// connect, login 
client.Connect(hostname, port); 
client.Login(username, password); 

// do some work 
// ... 

// disconnect 
client.Disconnect(); 
+0

Tengo mucha experiencia con la biblioteca Rebex FTP/FTPS y resolvió todos mis problemas. Recomiendo esta biblioteca, porque me ahorra mucho tiempo => dinero. – TcKs

-1

Acabo de tener el mismo problema.

Mi objetivo principal era subir un archivo a un ftp. Y no me importaba si mi tráfico pasaría por proxy o no.

Así que acabo de establecer la propiedad FTPWebRequest.Proxy en nulo justo después de FTPWebRequest.Create (uri).

Y funcionó. Sí, sé que esta solución no es la mejor. Y más de eso, no entiendo por qué funcionó. Pero el objetivo está completo, de todos modos.

+0

'Y no me importaba si mi tráfico pasaría por proxy o no. - ¿Pero tiene que conectarse a través de su proxy para conectarse a Internet o era simplemente opcional? –

2

La forma estándar de cargar contenido en una URL ftp: // a través de un proxy HTTP sería utilizando una solicitud HTTP PUT. Un proxy HTTP actúa como un HTTP < -> puerta de enlace FTP cuando se trata de ftp: // URL, hablando HTTP al cliente que realiza la solicitud y FTP al servidor FTP solicitado.

Al menos Squid HTTP Proxy admite PUT a ftp: // URLs, no estoy seguro de lo que hacen otros proxies.

La forma más común es abusar del método CONNECT para establecer túneles sobre el proxy. Pero esto a menudo no está permitido debido a las implicaciones de seguridad de permitir túneles bidireccionales sobre el proxy.

2

Hola tenía el mismo problema - la solución fue crear el objeto proxy y derivar los DefaultCredentials - esto debe ser proporcionada bien su aplicación se ha ejecutado con una cuenta de red -

FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); 

System.Net.WebProxy proxy = System.Net.WebProxy.GetDefaultProxy(); 
proxy.Credentials = System.Net.CredentialCache.DefaultCredentials; 

// set the ftpWebRequest proxy 
reqFTP.Proxy = proxy; 

Esto resuelve el problema para mi.

-1

No estoy seguro de si todos los proxies HTTP funcionan de la misma manera, pero logré engañar a los nuestros simplemente creando una solicitud HTTP para acceder al recurso en URI ftp://user:[email protected]/path.

Lamentablemente, para crear una instancia de HttpWebRequest debe usar WebRequest.Create. Y si lo hace, no puede crear una solicitud HTTP para ftp: // schema.

por lo que utiliza un poco de reflexión para invocar un constructor no pública, que hace eso:

var ctor = typeof(HttpWebRequest).GetConstructor(
    BindingFlags.NonPublic | BindingFlags.Instance, 
    null, 
    new Type[] { typeof(Uri), typeof(ServicePoint) }, 
    null); 
var req = (WebRequest)ctor.Invoke(new object[] { new Uri("ftp://user:[email protected]/test.txt"), null }); 
req.Proxy = new WebProxy("myproxy", 8080); 
req.Method = WebRequestMethods.Http.Put; 

using (var inStream = req.GetRequestStream()) 
{ 
    var buffer = Encoding.ASCII.GetBytes("test upload"); 
    inStream.Write(buffer, 0, buffer.Length); 
} 

using (req.GetResponse()) 
{ 
} 

También puede utilizar otros métodos como "BORRAR" para otras tareas.

En mi caso, funcionó a las mil maravillas.

0

¡Maldita estas aplicaciones y componentes no libres! Aquí está mi código C de código abierto que puede cargar archivos a FTP a través del proxy HTTP.

 public bool UploadFile(string localFilePath, string remoteDirectory) 
    { 
     var fileName = Path.GetFileName(localFilePath); 
     string content; 
     using (var reader = new StreamReader(localFilePath)) 
      content = reader.ReadToEnd(); 

     var proxyAuthB64Str = Convert.ToBase64String(Encoding.ASCII.GetBytes(_proxyUserName + ":" + _proxyPassword)); 
     var sendStr = "PUT ftp://" + _ftpLogin + ":" + _ftpPassword 
      + "@" + _ftpHost + remoteDirectory + fileName + " HTTP/1.1\n" 
      + "Host: " + _ftpHost + "\n" 
      + "User-Agent: Mozilla/4.0 (compatible; Eradicator; dotNetClient)\n" + "Proxy-Authorization: Basic " + proxyAuthB64Str + "\n" 
      + "Content-Type: application/octet-stream\n" 
      + "Content-Length: " + content.Length + "\n" 
      + "Connection: close\n\n" + content; 

     var sendBytes = Encoding.ASCII.GetBytes(sendStr); 

     using (var proxySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) 
     { 
      proxySocket.Connect(_proxyHost, _proxyPort); 
      if (!proxySocket.Connected) 
       throw new SocketException(); 
      proxySocket.Send(sendBytes); 

      const int recvSize = 65536; 
      var recvBytes = new byte[recvSize]; 
      proxySocket.Receive(recvBytes, recvSize, SocketFlags.Partial); 

      var responseFirstLine = new string(Encoding.ASCII.GetChars(recvBytes)).Split("\n".ToCharArray()).Take(1).ElementAt(0); 
      var httpResponseCode = Regex.Replace(responseFirstLine, @"HTTP/1\.\d (\d+) (\w+)", "$1"); 
      var httpResponseDescription = Regex.Replace(responseFirstLine, @"HTTP/1\.\d (\d+) (\w+)", "$2"); 
      return httpResponseCode.StartsWith("2"); 
     } 
     return false; 
    } 
3

A partir del marco .NET 4.6.3, la FtpWebRequest todavía cannot upload files over HTTP proxy.

Si el proxy especificado es un proxy HTTP, solo se admiten los comandos DownloadFile, ListDirectory y ListDirectoryDetails.

Por lo tanto, debe implementar la carga usted mismo o utilizar una biblioteca FTP de un tercero.


Por ejemplo, con WinSCP .NET assembly, puede utilizar:

// Setup session options 
SessionOptions sessionOptions = new SessionOptions 
{ 
    Protocol = Protocol.Ftp, 
    HostName = "example.com", 
    UserName = "user", 
    Password = "mypassword", 
}; 

// Configure proxy 
sessionOptions.AddRawSettings("ProxyMethod", "3"); 
sessionOptions.AddRawSettings("ProxyHost", "proxy"); 

using (Session session = new Session()) 
{ 
    // Connect 
    session.Open(sessionOptions); 

    // Upload file 
    string localFilePath = @"C:\path\file.txt"; 
    string pathUpload = "/file.txt"; 
    session.PutFiles(localFilePath, pathUpload).Check(); 
} 

Para las opciones de tje SessionOptions.AddRawSettings, ver raw settings.

Más fácil es tener WinSCP GUI generate C# FTP code template para usted.

Tenga en cuenta que el ensamblado WinSCP .NET no es una biblioteca .NET nativa. Es más bien un delgado contenedor .NET sobre una aplicación de consola.

(yo soy el autor de WinSCP)

+0

Voto a favor del autor de WinSCP. – zoidbeck