使用 HTTP 代理上传 FTP 文件
本文关键字:FTP 文件 HTTP 代理 使用 | 更新日期: 2023-09-27 17:47:23
有没有办法在HTTP代理后面将文件上传到FTP服务器?
似乎不支持使用 .Net Web 客户端的 HTTP 代理上传文件。(http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.proxy.aspx)。
如果没有解决方法?如果没有,你知道我可以使用的好的免费FTP库吗?
编辑:不幸的是,我没有任何FTP代理可以连接。
在活动 FTP 模式下,服务器启动与客户端的数据连接。如果客户端位于 HTTP 代理后面,这显然不起作用。在被动 FTP 模式下,客户端同时启动初始连接和数据连接。由于 HTTP 代理可以通过隧道传输任意传出 TCP 连接(使用 CONNECT 方法),因此应该可以通过 HTTP 代理以被动模式访问 FTP 服务器。
FtpWebRequest
似乎支持被动模式。但是,我不明白为什么支持文件下载和目录列表,而文件上传(也使用相同的数据连接)则不受支持。
您是否确认为被动模式配置FtpWebRequest
无法通过 HTTP 代理工作,通过该代理目录列表/文件下载工作正常?
大多数FTP代理在连接上执行操作,因此,如果您没有代理,则可以执行以下操作:
- 服务器:myftpserver.com
- 用户:我
- 密码:残疾人
使用 FTP 代理,您可以:
- 服务器:ftpproxy.mydomain.com
- 用户: me@myftpserver.com
- 密码:残疾人
它只是从那里解决它。我正在通过鱿鱼代理使用这个(试图调试某些东西)。
。但是由于您没有FTP代理....
你有袜子代理吗?这可能有效,但我不知道 .NET 是否可以做到。否则,老实说,我认为你被卡住了!与HTTP相比,FTP是一种"奇怪"协议,因为它具有控制通道(端口21)和数据通道(或多个,在随机端口上),因此通过代理是....至少可以说很有趣!
我们的 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();
从 .NET Framework 4.8 开始,FtpWebRequest
仍然无法通过 HTTP 代理上传文件。
如果指定的代理是 HTTP 代理,则仅支持 DownloadFile、ListDirectory 和 ListDirectoryDetails 命令。
它可能永远不会,因为FtpWebRequest
现在已经弃用了。因此,您需要使用第三方FTP库。
例如,对于 WinSCP .NET 程序集,您可以使用:
// 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
的选项,请参阅原始设置。
更容易的是让WinSCP GUI为您生成C# FTP代码模板。
请注意,WinSCP .NET 程序集不是本机 .NET 库。它是控制台应用程序上的一个薄的 .NET 包装器。
(我是WinSCP的作者)
一种解决方案是尝试 Mono 的 FtpWebRequest 实现。我看了一下它的源代码,似乎很容易修改,以便所有连接(控制和数据)都通过 HTTP 代理隧道传输。
您建立与 HTTP 代理而不是实际 FTP 服务器的 TCP 连接。然后发送CONNECT myserver:21 HTTP/1.0
后跟两个 CRLF (CRLF = ''r')。如果代理需要身份验证,则需要使用 HTTP/1.1,并发送带有凭据的代理身份验证标头。然后,您需要阅读响应的第一行。如果它以"HTTP/1.0 200
"或"HTTP/1.1 200
"开头,那么您(代码的其余部分)可以继续使用该连接,就好像它直接连接到FTP服务器一样。
如果有一种方法可以在没有 C# 的情况下通过 FTP 上传文件,那么在 C# 中也应该可以。通过浏览器或FTP客户端上传是否有效?
我最喜欢的一个FTP库是.NET FTP客户端库。
正如亚历山大所说,HTTP代理可以代理任意流量。 您需要的是一个支持使用 HTTP 代理的 FTP 客户端。 亚历山大也是正确的,这只能在被动模式下工作。
我的雇主出售这样的FTP客户端,但它是一个企业级工具,仅作为非常大系统的一部分提供。
我确信还有其他可用的可以更好地满足您的需求。
代理将内容上传到 ftp://URL 的标准方法是使用 HTTP PUT 请求。HTTP 代理在处理 ftp://URL 时充当 HTTP<->FTP 网关,向请求的客户端说出 HTTP,向请求的 FTP 服务器说 FTP。
至少Squid HTTP代理支持PUT到 ftp://URL,不确定其他代理的作用。
更常见的方法是滥用 CONNECT 方法来通过代理建立隧道。但由于允许通过代理建立双向隧道的安全隐患,这通常是不允许的。
我遇到了同样的问题 - 解决方案是创建代理对象并派生默认凭据 - 前提是您的应用程序是使用网络帐户运行的,这应该没问题 -
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;
这为我解决了问题。
该死的这些不自由的应用程序和组件!!这是我的开源 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;
}
我刚刚遇到了同样的问题。
我的主要目标是将文件上传到 ftp。而且我不在乎我的流量是否会通过代理。
所以我刚刚将FTPWebRequest.Proxy属性设置为null,紧跟在FTPWebRequest.Create(uri)之后。
它奏效了。是的,我知道这个解决方案不是最好的解决方案。更重要的是,我不明白为什么它会起作用。但无论如何,目标已经完成。
我不确定是否所有 HTTP 代理都以相同的方式工作,但我设法通过简单地创建一个 HTTP 请求来访问 URI ftp://user:pass@your.server.com/path 上的资源来欺骗我们的代理。
遗憾的是,要创建 HttpWebRequest 的实例,您应该使用 WebRequest.Create。如果这样做,则无法为 ftp://架构创建 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())
{
}
您还可以使用其他方法,例如"删除"来完成其他任务。
就我而言,它就像一个魅力。
Id 并没有真正看到 http 代理和上传到 ftp 服务器之间的连接。如果使用用于通过 http 代理访问 http 资源的 http 代理类。FTP 是另一种协议,FTP 代理使用不同的协议。