当使用HTTP代理时,是否有方法将文件上传到FTP服务器?
似乎使用.Net Webclient在HTTP代理后面不支持上传文件。(http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.proxy.aspx)。
如果没有解决方案?如果没有,你知道我可以使用哪个好用的免费FTP库吗?
编辑:很遗憾,我没有FTP代理连接。
当使用HTTP代理时,是否有方法将文件上传到FTP服务器?
似乎使用.Net Webclient在HTTP代理后面不支持上传文件。(http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.proxy.aspx)。
如果没有解决方案?如果没有,你知道我可以使用哪个好用的免费FTP库吗?
编辑:很遗憾,我没有FTP代理连接。
大多数FTP代理都在连接时进行操作,因此如果您没有代理,则可以执行以下操作:
使用FTP代理,您需要执行以下操作:
然后它会自动解决。我正在通过squid代理(尝试调试某些内容)使用这个方法。
但是,如果您没有FTP代理...
您有SOCKS代理吗?那可能行得通,但我不知道.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();
FtpWebRequest
仍然不能通过HTTP代理上传文件。如果指定的代理是HTTP代理,则仅支持DownloadFile、ListDirectory和ListDirectoryDetails命令。而且它可能永远都不会支持,因为FtpWebRequest
现已弃用。所以你需要使用第三方FTP库。// 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的作者)
CONNECT myserver:21 HTTP/1.0
,然后是两个CRLFs(CRLF = \r\n)。如果代理需要身份验证,则需要使用HTTP/1.1,并在凭据中发送代理身份验证标头。然后,您需要读取响应的第一行。如果以"HTTP/1.0 200
"或"HTTP/1.1 200
"开头,则您(其余代码)可以继续使用该连接,就像直接连接到FTP服务器一样。如果你能通过FTP上传文件,而不需要使用C#,那么在C#中也应该可以实现。是否可以通过浏览器或FTP客户端上传?
我最喜欢的FTP库是.NET FTP Client library。
你好,我遇到了同样的问题 - 解决方法是创建代理对象并派生默认凭据 - 只要你的应用程序使用网络帐户运行,这应该是可以的 -
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;
}