我使用此库连接到远程FTP服务器并下载库存(csv)文件:https://netftp.codeplex.com/
我已经完成了连接,下载和安装;包装器中的断开序列如下:
class FTPConnection
{
/// <summary>
/// Private class objects.
/// </summary>
private string ftpHost;
private string ftpUser;
private string ftpPass;
private string ftpDocRoot;
private int ftpPort;
private int ftpTimeout;
private FtpClient ftpClient;
/// <summary>
/// Class constructor.
/// </summary>
/// <param name="ftpHost"></param>
/// <param name="ftpPort"></param>
/// <param name="ftpUser"></param>
/// <param name="ftpPass"></param>
/// <param name="ftpDocRoot"></param>
/// <param name="ftpTimeout"></pparam>
public FTPConnection(string ftpHost, int ftpPort, string ftpUser, string ftpPass, string ftpDocRoot, int ftpTimeout = 30)
{
// Remember settings
this.ftpHost = ftpHost;
this.ftpPort = ftpPort;
this.ftpUser = ftpUser;
this.ftpPass = ftpPass;
this.ftpDocRoot = ftpDocRoot;
this.ftpTimeout = ftpTimeout;
}
/// <summary>
/// Method to test connection.
/// </summary>
/// <returns></returns>
public bool Test()
{
// Connect to ftp server
Connect();
// Check if connected
bool isConnected = ftpClient.IsConnected;
// Disconnect
Disconnect();
// Finished
return isConnected;
}
/// <summary>
/// Method to download stock file from ftp server.
/// </summary>
/// <param name="stockFileDir"></param>
/// <param name="supplierId"></param>
/// <param name="stockFileNamePattern"></param>
/// <returns></returns>
public string DownloadStockFile(string stockFileDir, int supplierId, string stockFileNamePattern)
{
// Init
string localFilePath = "";
// Connect to ftp server
Connect();
// Load remote ftp server files
foreach (FtpListItem ftpListItem in ftpClient.GetListing(stockFileDir, FtpListOption.Modify | FtpListOption.Size))
{
if (ftpListItem.Type == FtpFileSystemObjectType.File && ftpListItem.Name.Contains(stockFileNamePattern))
{
localFilePath = string.Format(@"{0}\{1}_{2}", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), supplierId, ftpListItem.Name);
if (File.Exists(localFilePath)) File.Delete(localFilePath);
using (var ftpStream = ftpClient.OpenRead(ftpListItem.FullName))
using (var fileStream = File.Create(localFilePath, (int)ftpStream.Length))
{
var buffer = new byte[8 * 1024];
int count;
while ((count = ftpStream.Read(buffer, 0, buffer.Length)) > 0)
{
fileStream.Write(buffer, 0, count);
}
break;
}
}
}
// Disconnect
Disconnect();
// Finished
return localFilePath;
}
/// <summary>
/// Method to connect to ftp server.
/// </summary>
private void Connect()
{
// Connect to ftp server
if (null == ftpClient || !ftpClient.IsConnected)
{
ftpClient = new FtpClient();
ftpClient.Encoding = Encoding.UTF8;
ftpClient.Host = ftpHost;
ftpClient.Port = ftpPort;
ftpClient.ConnectTimeout = 1000 * ftpTimeout;
ftpClient.Credentials = new NetworkCredential(ftpUser, ftpPass);
ftpClient.Connect();
ftpClient.SetWorkingDirectory(ftpDocRoot);
}
}
/// <summary>
/// Method to disconnect from ftp server.
/// </summary>
private void Disconnect()
{
try
{
ftpClient.Disconnect();
}
catch { }
finally
{
if (null != ftpClient)
ftpClient.Dispose();
ftpClient = null;
}
}
}
这用于“同步”应用程序,该应用程序轮询ftp服务器并按文件名模式抓取第一个匹配的文件。
这就是我使用包装器的方式:
// Init
string stockFilePath = string.Empty;
// Connect to ftp server and download the stock file
FTPConnection ftpConnection = null;
try
{
// Init connection
ftpConnection = new FTPConnection
(
supplierConfig.FTPHost,
supplierConfig.FTPPort,
supplierConfig.FTPUser,
supplierConfig.FTPPass,
supplierConfig.FTPDir
);
// Download stock file
stockFilePath = ftpConnection.DownloadStockFile(supplierConfig.FTPDir, supplierConfig.PLSupplierAccountID, supplierConfig.StockFileNamePattern);
}
catch (Exception ex)
{
// Re throw exception
throw new Exception("Failed to download stock file - " + ex.Message);
}
finally
{
// Clean-up
ftpConnection = null;
}
代码执行时,它完全按预期工作。抓取文件并存储它并返回本地文件的完整路径。
然而,当代码再次执行时(在设定的间隔之后),我不断收到此错误:
已达到您帐户的最大连接数(4)。
但是,您可以在我的包装器中看到我正在关闭ftp连接并处理ftp客户端对象并进行清理。
知道我如何达到4
的ftp帐户的最大连接数?
如果我要关闭应用并打开它,它会再次开始正常工作。这是远程ftp服务器的问题吗?它看起来只能连接一次。
答案 0 :(得分:0)
您可以尝试将客户端包装在using块中,以查看是否可以重复连接整个对象:
using (FtpClient conn = new FtpClient()) {
FtpReply reply;
conn.Host = "localhost";
conn.Credentials = new NetworkCredential("ftptest", "ftptest");
if (!(reply = conn.Execute("SITE CHMOD 640 FOO.TXT")).Success) {
throw new FtpCommandException(reply);
}
}
答案 1 :(得分:0)
ftpConnection = null;
没有关闭你的conn,你必须致电ftpConnection.Disconnect()
答案 2 :(得分:0)
我已经通过浏览System.Data.FtpClient
上的可用选项来解决问题,看看它是否有KeepAlive
/ MaxConnection
等的任何方法/设置....我遇到了这个选项:
以下是此选项的作用:
当此值设置为true(默认值)时,将克隆控件连接 以及为数据通道操作建立服务器的新连接。 这是一种在单个上进行异步操作的线程安全方法 控制连接对开发人员来说是透明的。
所以,我已将此设置为false
(因为我没有使用async
方法),如下所示:
conn.EnableThreadSafeDataConnections = false;
我的问题解决了。基本上发生了什么,这个库保持连接打开,每次我断开(最多4个)像某种连接池。将此设置为false会阻止它执行此操作。
这是我的代码的最终工作版本:
/// <summary>
/// Method to download stock file from ftp server.
/// </summary>
/// <param name="stockFileDir"></param>
/// <param name="supplierId"></param>
/// <param name="stockFileNamePattern"></param>
/// <returns></returns>
public string DownloadStockFile(string stockFileDir, int supplierId, string stockFileNamePattern)
{
// Init
string localFilePath = "";
// Load remote ftp server file
using (FtpClient conn = new FtpClient())
{
// Set connection details
conn.Encoding = Encoding.UTF8;
conn.Host = ftpHost;
conn.Port = ftpPort;
conn.ConnectTimeout = 1000 * ftpTimeout;
conn.Credentials = new NetworkCredential(ftpUser, ftpPass);
conn.EnableThreadSafeDataConnections = false;
// Get file listng
foreach (FtpListItem ftpListItem in conn.GetListing(stockFileDir, FtpListOption.Modify | FtpListOption.Size))
{
// Proceed if this is a file
if (ftpListItem.Type == FtpFileSystemObjectType.File && ftpListItem.Name.Contains(stockFileNamePattern))
{
// Download file
localFilePath = string.Format(@"{0}\{1}_{2}", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), supplierId, ftpListItem.Name);
if (File.Exists(localFilePath)) File.Delete(localFilePath);
using (var ftpStream = conn.OpenRead(ftpListItem.FullName))
using (var fileStream = File.Create(localFilePath, (int)ftpStream.Length))
{
var buffer = new byte[8 * 1024];
int count;
while ((count = ftpStream.Read(buffer, 0, buffer.Length)) > 0)
{
fileStream.Write(buffer, 0, count);
}
// Stop further processing
break;
}
}
}
// Disconnect
conn.Disconnect();
}
// Finished
return localFilePath;
}
希望这有助于某人。