使用HTTP代理进行FTP文件上载

时间:2008-10-02 07:23:22

标签: c# proxy ftp

在HTTP代理后面有没有办法将文件上传到FTP服务器?

使用.Net Webclient的HTTP代理似乎不支持上传文件。 (http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.proxy.aspx)。

如果没有解决方法?如果没有,你知道我可以使用一个好的免费FTP库吗?

修改:很遗憾,我没有任何FTP代理可以连接。

13 个答案:

答案 0 :(得分:9)

在主动FTP模式下,服务器启动与客户端的数据连接。如果客户端在HTTP代理后面,这显然不起作用。在被动FTP模式下,客户端启动初始连接和数据连接。由于HTTP代理可以隧道传输任意传出TCP连接(使用CONNECT方法),因此应该可以通过HTTP代理以被动模式访问FTP服务器。

FtpWebRequest似乎支持被动模式。但是,我不明白为什么支持文件下载和目录列表,而文件上载也使用相同的数据连接,而不是。

您是否确认为被动模式配置的FtpWebRequest无法通过HTTP代理工作,目录列表/文件下载工作正常?

答案 1 :(得分:5)

大多数FTP代理都在连接上执行操作,因此如果您没有代理,则执行以下操作:

  • 服务器:myftpserver.com
  • 用户:我
  • 密码:pwd

使用FTP代理,您可以:

  • 服务器:ftpproxy.mydomain.com
  • user:me@myftpserver.com
  • 密码:pwd

它只是从那里开始工作。我正在通过鱿鱼代理使用这个正确的第二个(试图调试一些东西)。

...但是因为你没有FTP代理....

你有SOCKS代理吗?这可能会奏效,但我不知道.NET是否可以做到这一点。否则,说实话,我觉得你被卡住了!与HTTP相比,FTP是一种“奇怪的”协议,因为它有一个控制通道(端口21)和一个数据通道(或多个,在随机端口上),所以通过代理进入是有趣的。至少说!

答案 2 :(得分:5)

我们的Rebex FTP/SSL可以使用HTTP代理。它不是免费的,但是......

// 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();

答案 3 :(得分:3)

一种解决方案是尝试Mono的FtpWebRequest实现。我查看了它的源代码,看起来很容易修改,以便所有连接(控制和数据)都通过HTTP代理进行隧道传输。

建立与HTTP代理的TCP连接,而不是实际的FTP服务器。然后发送CONNECT myserver:21 HTTP/1.0,然后发送两个CRLF(CRLF = \ r \ n)。如果代理需要身份验证,则需要使用HTTP / 1.1并使用凭据发送代理身份验证标头。然后你需要阅读响应的第一行。如果它以“HTTP/1.0 200 ”或“HTTP/1.1 200 ”开头,那么您(其余代码)可以继续使用连接,就像它直接连接到FTP服务器一样。

答案 4 :(得分:3)

从.NET framework 4.7.2开始,FtpWebRequest仍为cannot upload files over HTTP proxy

  

如果指定的代理是HTTP代理,则仅支持DownloadFile,ListDirectory和ListDirectoryDe​​tails命令。

因此,您需要自己实施上传,或使用第三方FTP库。

例如,使用WinSCP .NET assembly,您可以使用:

// 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();
}

有关SessionOptions.AddRawSettings的选项,请参阅raw settings

更容易为您安装WinSCP GUI generate C# FTP code template

请注意,WinSCP .NET程序集不是本机.NET库。它相当于控制台应用程序上的瘦.NET包装。

(我是WinSCP的作者)

答案 5 :(得分:2)

如果有一种方法可以通过FTP 上传文件而不用 C#,那么它也应该可以在C#中使用。通过浏览器或FTP客户端上传是否有效?

我最喜欢的一个FTP库是.NET FTP Client library

答案 6 :(得分:2)

正如亚历山大所说,HTTP代理可以代理任意流量。您需要的是支持使用HTTP代理的FTP客户端。亚历山大也是正确的,这只会在被动模式下工作。

我的雇主销售这样一个FTP客户端,但它是一个企业级工具,只是作为一个非常大的系统的一部分。

我确信还有其他可用的东西可以更好地满足您的需求。

答案 7 :(得分:2)

通过HTTP代理将内容上传到ftp:// URL的标准方法是使用HTTP PUT请求。当处理ftp:// URL,向请求客户端说HTTP并向请求的FTP服务器发送FTP时,HTTP代理充当HTTP< - > FTP网关。

至少Squid HTTP代理支持PUT到ftp:// URL,不知道其他代理做了什么。

更常见的方法是滥用CONNECT方法在代理上建立隧道。但由于允许双向隧道通过代理的安全隐患,通常不允许这样做。

答案 8 :(得分:2)

您好我有同样的问题 - 解决方案是创建代理对象并派生defaultcredentials - 如果您的应用程序已使用网络帐户运行,这应该没问题 -

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;

这解决了我的问题。

答案 9 :(得分:0)

该死的应用程序和组件! 这是我的开源C#代码,可以通过HTTP代理将文件上传到FTP。

        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;
    }

答案 10 :(得分:-1)

我刚遇到同样的问题。

我的主要目标是将文件上传到ftp。而且我不在乎我的流量是否会通过代理。

所以我在FTPWebRequest.Create(uri)之后立即将FTPWebRequest.Proxy属性设置为null。

它有效。是的,我知道这个解决方案不是最好的解决方案。更重要的是,我不明白为什么它有效。但无论如何,目标是完整的。

答案 11 :(得分:-1)

我不确定所有HTTP代理是否都以相同的方式工作,但我设法通过简单地创建HTTP请求来访问URI ftp://user:pass@your.server.com/path上的资源来欺骗我们。

遗憾的是,要创建HttpWebRequest的实例,您应该使用WebRequest.Create。如果这样做,则无法为ftp:// schema创建HTTP请求。

所以我使用了一些反射来调用一个非公共构造函数来执行该操作:

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:pass@host/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())
{
}

您还可以使用“DELETE”等其他方法执行其他任务。

就我而言,它就像一个魅力。

答案 12 :(得分:-5)

我真的没有看到http代理和上传到ftp服务器之间的连接。如果您使用http代理类来通过http代理访问http资源。 ftp是另一种协议,ftp代理使用不同的协议。