csharp:FTP Client Library using FtpWebRequest or Sockets
https://netftp.codeplex.com/SourceControl/latest
http://ftplib.codeplex.com/
https://www.codeproject.com/articles/18537/c-ftp-client-library
https://www.codeproject.com/Articles/31624/An-FTP-secure-client-library-for-C
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Runtime; namespace ftpdemo
{ /// <summary>
///
/// </summary>
public partial class Form2 : Form
{
string ftpServerIP;
string ftpUserID;
string ftpPassword;
/// <summary>
///
/// </summary>
public Form2()
{
InitializeComponent();
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form2_Load(object sender, EventArgs e)
{
ftpServerIP = "88.88.88.88";//
ftpUserID = "dusystem.com";//dusystem.com
ftpPassword = "geovindu";////
txtServerIP.Text = ftpServerIP;
txtUsername.Text = ftpUserID;
txtPassword.Text = ftpPassword;
this.Text += ftpServerIP; btnFTPSave.Enabled = false;
} /// <summary>
/// Method to upload the specified file to the specified FTP Server
/// 隻能是根目錄下,要解決這個問題
/// 上传,必须存在文件夹下。
/// 最好是不要用中文名称文件夹或文件
/// </summary>
/// <param name="filename">file full name to be uploaded</param>
private void Upload(string filename)
{
FileInfo fileInf = new FileInfo(filename);
string uri = "ftp://" + ftpServerIP + "/" + fileInf.Name;
FtpWebRequest reqFTP; // Create FtpWebRequest object from the Uri provided
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + fileInf.Name)); // Provide the WebPermission Credintials
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); // By default KeepAlive is true, where the control connection is not closed
// after a command is executed.
reqFTP.KeepAlive = false; // Specify the command to be executed.
reqFTP.Method = WebRequestMethods.Ftp.UploadFile; // Specify the data transfer type.
reqFTP.UseBinary = true; // Notify the server about the size of the uploaded file
reqFTP.ContentLength = fileInf.Length; // The buffer size is set to 2kb
int buffLength = 2048;
byte[] buff = new byte[buffLength];
int contentLen; // Opens a file stream (System.IO.FileStream) to read the file to be uploaded
FileStream fs = fileInf.OpenRead(); try
{
// Stream to which the file to be upload is written
Stream strm = reqFTP.GetRequestStream(); // Read from the file stream 2kb at a time
contentLen = fs.Read(buff, 0, buffLength); // Till Stream content ends
while (contentLen != 0)
{
// Write Content from the file stream to the FTP Upload Stream
strm.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
} // Close the file stream and the Request Stream
strm.Close();
fs.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Upload Error");
}
}
/// <summary>
/// 删除
/// </summary>
/// <param name="fileName"></param>
public void DeleteFTP(string fileName)
{
try
{
string uri = "ftp://" + ftpServerIP + "/" + fileName;
FtpWebRequest reqFTP;
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + fileName)); reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
reqFTP.KeepAlive = false;
reqFTP.Method = WebRequestMethods.Ftp.DeleteFile; string result = String.Empty;
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
long size = response.ContentLength;
Stream datastream = response.GetResponseStream();
StreamReader sr = new StreamReader(datastream);
result = sr.ReadToEnd();
sr.Close();
datastream.Close();
response.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "FTP 2.0 Delete");
}
}
/// <summary>
/// 要得到文件名,文件夾,文件地址,文件大小,文件建立時間
/// 获取文件和文件夹列表
/// </summary>
/// <returns></returns>
private string[] GetFilesDetailList()
{
string[] downloadFiles;
try
{
StringBuilder result = new StringBuilder();
FtpWebRequest ftp;
ftp = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/"));
ftp.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
WebResponse response = ftp.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default); //遍曆讀文件信息
string line = reader.ReadLine(); while (line != null)
{
result.Append(line);
result.Append("\n");
line = reader.ReadLine();
} result.Remove(result.ToString().LastIndexOf("\n"), 1);
reader.Close();
response.Close();
return result.ToString().Split('\n');
//MessageBox.Show(result.ToString().Split('\n'));
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
downloadFiles = null;
return downloadFiles;
}
}
/// <summary>
/// 获取文件列表
/// </summary>
/// <returns></returns>
public string[] GetFileList()
{
string[] downloadFiles;
StringBuilder result = new StringBuilder();
FtpWebRequest reqFTP;
try
{
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/"));
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;
WebResponse response = reqFTP.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default); //MessageBox.Show(reader.ReadToEnd());
string line = reader.ReadLine();
while (line != null)
{
result.Append(line);
result.Append("\n");
line = reader.ReadLine();
}
result.Remove(result.ToString().LastIndexOf('\n'), 1);
reader.Close();
response.Close();
//MessageBox.Show(response.StatusDescription);
return result.ToString().Split('\n');
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
downloadFiles = null;
return downloadFiles;
}
}
/// <summary>
/// 下载
/// </summary>
/// <param name="filePath"></param>
/// <param name="fileName"></param>
private void Download(string filePath, string fileName)
{
FtpWebRequest reqFTP;
try
{
//filePath = <<The full path where the file is to be created.>>,
//fileName = <<Name of the file to be created(Need not be the name of the file on FTP server).>>
FileStream outputStream = new FileStream(filePath + "\\" + fileName, FileMode.Create); reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + fileName));
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream();
long cl = response.ContentLength;
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[bufferSize]; readCount = ftpStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
outputStream.Write(buffer, 0, readCount);
readCount = ftpStream.Read(buffer, 0, bufferSize);
} ftpStream.Close();
outputStream.Close();
response.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// <summary>
/// 上传
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnUpload_Click(object sender, EventArgs e)
{
OpenFileDialog opFilDlg = new OpenFileDialog();
if (opFilDlg.ShowDialog() == DialogResult.OK)
{
Upload(opFilDlg.FileName);
}
}
/// <summary>
/// 下载
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnDownload_Click(object sender, EventArgs e)
{
FolderBrowserDialog fldDlg = new FolderBrowserDialog();
if (txtUpload.Text.Trim().Length > 0)
{
if (fldDlg.ShowDialog() == DialogResult.OK)
{
Download(fldDlg.SelectedPath, txtUpload.Text.Trim());
}
}
else
{
MessageBox.Show("Please enter the File name to download");
}
}
/// <summary>
/// 删除文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btndelete_Click(object sender, EventArgs e)
{
OpenFileDialog fldDlg = new OpenFileDialog();
if (txtUpload.Text.Trim().Length > 0)
{
DeleteFTP(txtUpload.Text.Trim());
}
else
{
MessageBox.Show("Please enter the File name to delete");
}
}
/// <summary>
///
/// </summary>
/// <param name="filename"></param>
/// <returns></returns>
private long GetFileSize(string filename)
{
FtpWebRequest reqFTP;
long fileSize = 0;
try
{
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + filename));
reqFTP.Method = WebRequestMethods.Ftp.GetFileSize;
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream();
fileSize = response.ContentLength; ftpStream.Close();
response.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return fileSize;
}
/// <summary>
/// 计算文件大小
/// </summary>
/// <returns></returns>
public string setSize(long size)
{
string strszie = string.Empty; long g = 1024 * 1024 * 1024;
long m = 1024 * 1024;
long k = 1024;
if (size < k && size >= 1)
{
strszie = size.ToString("0.00") + "B";
}
else if (size < m && size >= 1024)
{
strszie = (size / k).ToString("0.00") + "KB";
}
else if (size < g && size >= m)
{
strszie = (size / m).ToString("0.00") + "MB";
}
else if (size >= g)
{
strszie = (size / g).ToString("0.00") + "GB";
} return strszie; }
/// <summary>
/// 改名
/// </summary>
/// <param name="currentFilename"></param>
/// <param name="newFilename"></param>
private void Rename(string currentFilename, string newFilename)
{
FtpWebRequest reqFTP;
try
{
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + currentFilename));
reqFTP.Method = WebRequestMethods.Ftp.Rename;
reqFTP.RenameTo = newFilename;
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream(); ftpStream.Close();
response.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// <summary>
///
/// </summary>
/// <param name="dirName"></param>
private void MakeDir(string dirName)
{
FtpWebRequest reqFTP;
try
{
// dirName = name of the directory to create.
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + dirName));
reqFTP.Method = WebRequestMethods.Ftp.MakeDirectory;
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream(); ftpStream.Close();
response.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// <summary>
/// 文件大小
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnFileSize_Click(object sender, EventArgs e)
{
long size = GetFileSize(txtUpload.Text.Trim());
string s = setSize(size);
//MessageBox.Show(size.ToString() + " bytes");
MessageBox.Show(s);
}
/// <summary>
/// 改名
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
Rename(txtCurrentFilename.Text.Trim(), txtNewFilename.Text.Trim());
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnewDir_Click(object sender, EventArgs e)
{
MakeDir(txtNewDir.Text.Trim());
}
/// <summary>
/// 显示文件列表
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnLstFiles_Click(object sender, EventArgs e)
{
string[] filenames = GetFileList();
lstFiles.Items.Clear();
foreach (string filename in filenames)
{
lstFiles.Items.Add(filename);
}
}
/// <summary>
/// 显示文件和文件夹列表
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnFileDetailList_Click(object sender, EventArgs e)
{
string[] filenames = GetFilesDetailList();
lstFiles.Items.Clear();
foreach (string filename in filenames)
{
lstFiles.Items.Add(filename);
}
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnFTPSave_Click(object sender, EventArgs e)
{
ftpServerIP = txtServerIP.Text.Trim();
ftpUserID = txtUsername.Text.Trim();
ftpPassword = txtPassword.Text.Trim();
btnFTPSave.Enabled = false;
} private void txtServerIP_TextChanged(object sender, EventArgs e)
{
btnFTPSave.Enabled = true;
} private void txtUsername_TextChanged(object sender, EventArgs e)
{
btnFTPSave.Enabled = true;
} private void txtPassword_TextChanged(object sender, EventArgs e)
{
btnFTPSave.Enabled = true;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.IO;
using System.Text;
using System.Net.Sockets; namespace ftpdemo
{
/// <summary>
///
/// </summary>
public class FTPClient
{
#region 构造函数
/// <summary>
/// 缺省构造函数
/// </summary>
public FTPClient()
{
strRemoteHost = "";
strRemotePath = "";
strRemoteUser = "";
strRemotePass = "";
strRemotePort = 21;
bConnected = false;
} /// <summary>
/// 构造函数
/// </summary>
/// <param name="remoteHost">FTP服务器IP地址</param>
/// <param name="remotePath">当前服务器目录</param>
/// <param name="remoteUser">登录用户账号</param>
/// <param name="remotePass">登录用户密码</param>
/// <param name="remotePort">FTP服务器端口</param>
public FTPClient(string remoteHost, string remotePath, string remoteUser, string remotePass, int remotePort)
{
strRemoteHost = remoteHost;
strRemotePath = remotePath;
strRemoteUser = remoteUser;
strRemotePass = remotePass;
strRemotePort = remotePort;
Connect();
}
#endregion #region 登陆字段、属性
/// <summary>
/// FTP服务器IP地址
/// </summary>
private string strRemoteHost;
public string RemoteHost
{
get
{
return strRemoteHost;
}
set
{
strRemoteHost = value;
}
}
/// <summary>
/// FTP服务器端口
/// </summary>
private int strRemotePort;
public int RemotePort
{
get
{
return strRemotePort;
}
set
{
strRemotePort = value;
}
}
/// <summary>
/// 当前服务器目录
/// </summary>
private string strRemotePath;
public string RemotePath
{
get
{
return strRemotePath;
}
set
{
strRemotePath = value;
}
}
/// <summary>
/// 登录用户账号
/// </summary>
private string strRemoteUser;
public string RemoteUser
{
set
{
strRemoteUser = value;
}
}
/// <summary>
/// 用户登录密码
/// </summary>
private string strRemotePass;
public string RemotePass
{
set
{
strRemotePass = value;
}
} /// <summary>
/// 是否登录
/// </summary>
private Boolean bConnected;
public bool Connected
{
get
{
return bConnected;
}
}
#endregion #region 链接
/// <summary>
/// 建立连接
/// </summary>
public void Connect()
{
socketControl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(RemoteHost), strRemotePort);
// 链接
try
{
socketControl.Connect(ep);
}
catch (Exception)
{
throw new IOException("Couldn't connect to remote server");
} // 获取应答码
ReadReply();
if (iReplyCode != 220)
{
DisConnect();
throw new IOException(strReply.Substring(4));
} // 登陆
SendCommand("USER " + strRemoteUser);
if (!(iReplyCode == 331 || iReplyCode == 230))
{
CloseSocketConnect();//关闭连接
throw new IOException(strReply.Substring(4));
}
if (iReplyCode != 230)
{
SendCommand("PASS " + strRemotePass);
if (!(iReplyCode == 230 || iReplyCode == 202))
{
CloseSocketConnect();//关闭连接
throw new IOException(strReply.Substring(4));
}
}
bConnected = true; // 切换到初始目录
if (!string.IsNullOrEmpty(strRemotePath))
{
ChDir(strRemotePath);
}
} /// <summary>
/// 关闭连接
/// </summary>
public void DisConnect()
{
if (socketControl != null)
{
SendCommand("QUIT");
}
CloseSocketConnect();
} #endregion #region 传输模式 /// <summary>
/// 传输模式:二进制类型、ASCII类型
/// </summary>
public enum TransferType
{
Binary,
ASCII
}; /// <summary>
/// 设置传输模式
/// </summary>
/// <param name="ttType">传输模式</param>
public void SetTransferType(TransferType ttType)
{
if (ttType == TransferType.Binary)
{
SendCommand("TYPE I");//binary类型传输
}
else
{
SendCommand("TYPE A");//ASCII类型传输
}
if (iReplyCode != 200)
{
throw new IOException(strReply.Substring(4));
}
else
{
trType = ttType;
}
} /// <summary>
/// 获得传输模式
/// </summary>
/// <returns>传输模式</returns>
public TransferType GetTransferType()
{
return trType;
} #endregion #region 文件操作
/// <summary>
/// 获得文件列表
/// </summary>
/// <param name="strMask">文件名的匹配字符串</param>
/// <returns></returns>
public string[] Dir(string strMask)
{
// 建立链接
if (!bConnected)
{
Connect();
} //建立进行数据连接的socket
Socket socketData = CreateDataSocket(); //传送命令
SendCommand("LIST " + strMask); //分析应答代码
if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226))
{
throw new IOException(strReply.Substring(4));
} //获得结果
strMsg = "";
while (true)
{
int iBytes = socketData.Receive(buffer, buffer.Length, 0);
strMsg += GB2312.GetString(buffer, 0, iBytes);
if (iBytes < buffer.Length)
{
break;
}
}
char[] seperator = { '\n' };
string[] strsFileList = strMsg.Split(seperator);
socketData.Close();//数据socket关闭时也会有返回码
if (iReplyCode != 226)
{
ReadReply();
if (iReplyCode != 226)
{
throw new IOException(strReply.Substring(4));
}
}
return strsFileList;
} /// <summary>
/// 获取文件大小
/// </summary>
/// <param name="strFileName">文件名</param>
/// <returns>文件大小</returns>
public long GetFileSize(string strFileName)
{
if (!bConnected)
{
Connect();
}
SendCommand("SIZE " + Path.GetFileName(strFileName));
long lSize = 0;
if (iReplyCode == 213)
{
lSize = Int64.Parse(strReply.Substring(4));
}
else
{
throw new IOException(strReply.Substring(4));
}
return lSize;
} /// <summary>
/// 删除
/// </summary>
/// <param name="strFileName">待删除文件名</param>
public void Delete(string strFileName)
{
if (!bConnected)
{
Connect();
}
SendCommand("DELE " + strFileName);
if (iReplyCode != 250)
{
throw new IOException(strReply.Substring(4));
}
} /// <summary>
/// 重命名(如果新文件名与已有文件重名,将覆盖已有文件)
/// </summary>
/// <param name="strOldFileName">旧文件名</param>
/// <param name="strNewFileName">新文件名</param>
public void Rename(string strOldFileName, string strNewFileName)
{
if (!bConnected)
{
Connect();
}
SendCommand("RNFR " + strOldFileName);
if (iReplyCode != 350)
{
throw new IOException(strReply.Substring(4));
}
// 如果新文件名与原有文件重名,将覆盖原有文件
SendCommand("RNTO " + strNewFileName);
if (iReplyCode != 250)
{
throw new IOException(strReply.Substring(4));
}
}
#endregion #region 上传和下载
/// <summary>
/// 下载一批文件
/// </summary>
/// <param name="strFileNameMask">文件名的匹配字符串</param>
/// <param name="strFolder">本地目录(不得以\结束)</param>
public void Get(string strFileNameMask, string strFolder)
{
if (!bConnected)
{
Connect();
}
string[] strFiles = Dir(strFileNameMask);
foreach (string strFile in strFiles)
{
if (!strFile.Equals(""))//一般来说strFiles的最后一个元素可能是空字符串
{
if (strFile.LastIndexOf(".") > -1)
{
Get(strFile.Replace("\r", ""), strFolder, strFile.Replace("\r", ""));
}
}
}
} /// <summary>
/// 下载目录
/// </summary>
/// <param name="strRemoteFileName">要下载的文件名</param>
/// <param name="strFolder">本地目录(不得以\结束)</param>
/// <param name="strLocalFileName">保存在本地时的文件名</param>
public void Get(string strRemoteFileName, string strFolder, string strLocalFileName)
{
if (strLocalFileName.StartsWith("-r"))
{
string[] infos = strLocalFileName.Split(' ');
strRemoteFileName = strLocalFileName = infos[infos.Length - 1]; if (!bConnected)
{
Connect();
}
SetTransferType(TransferType.Binary);
if (strLocalFileName.Equals(""))
{
strLocalFileName = strRemoteFileName;
}
if (!File.Exists(strLocalFileName))
{
Stream st = File.Create(strLocalFileName);
st.Close();
} FileStream output = new
FileStream(strFolder + "\\" + strLocalFileName, FileMode.Create);
Socket socketData = CreateDataSocket();
SendCommand("RETR " + strRemoteFileName);
if (!(iReplyCode == 150 || iReplyCode == 125
|| iReplyCode == 226 || iReplyCode == 250))
{
throw new IOException(strReply.Substring(4));
}
while (true)
{
int iBytes = socketData.Receive(buffer, buffer.Length, 0);
output.Write(buffer, 0, iBytes);
if (iBytes <= 0)
{
break;
}
}
output.Close();
if (socketData.Connected)
{
socketData.Close();
}
if (!(iReplyCode == 226 || iReplyCode == 250))
{
ReadReply();
if (!(iReplyCode == 226 || iReplyCode == 250))
{
throw new IOException(strReply.Substring(4));
}
}
}
} /// <summary>
/// 下载一个文件
/// </summary>
/// <param name="strRemoteFileName">要下载的文件名</param>
/// <param name="strFolder">本地目录(不得以\结束)</param>
/// <param name="strLocalFileName">保存在本地时的文件名</param>
public void GetFile(string strRemoteFileName, string strFolder, string strLocalFileName)
{
if (!bConnected)
{
Connect();
}
SetTransferType(TransferType.Binary);
if (strLocalFileName.Equals(""))
{
strLocalFileName = strRemoteFileName;
}
if (!File.Exists(strLocalFileName))
{
Stream st = File.Create(strLocalFileName);
st.Close();
} FileStream output = new
FileStream(strFolder + "\\" + strLocalFileName, FileMode.Create);
Socket socketData = CreateDataSocket();
SendCommand("RETR " + strRemoteFileName);
if (!(iReplyCode == 150 || iReplyCode == 125
|| iReplyCode == 226 || iReplyCode == 250))
{
throw new IOException(strReply.Substring(4));
}
while (true)
{
int iBytes = socketData.Receive(buffer, buffer.Length, 0);
output.Write(buffer, 0, iBytes);
if (iBytes <= 0)
{
break;
}
}
output.Close();
if (socketData.Connected)
{
socketData.Close();
}
if (!(iReplyCode == 226 || iReplyCode == 250))
{
ReadReply();
if (!(iReplyCode == 226 || iReplyCode == 250))
{
throw new IOException(strReply.Substring(4));
}
}
} /// <summary>
/// 下载一个文件
/// </summary>
/// <param name="strRemoteFileName">要下载的文件名</param>
/// <param name="strFolder">本地目录(不得以\结束)</param>
/// <param name="strLocalFileName">保存在本地时的文件名</param>
public void GetBrokenFile(string strRemoteFileName, string strFolder, string strLocalFileName, long size)
{
if (!bConnected)
{
Connect();
}
SetTransferType(TransferType.Binary); FileStream output = new
FileStream(strFolder + "\\" + strLocalFileName, FileMode.Append);
Socket socketData = CreateDataSocket();
SendCommand("REST " + size.ToString());
SendCommand("RETR " + strRemoteFileName);
if (!(iReplyCode == 150 || iReplyCode == 125
|| iReplyCode == 226 || iReplyCode == 250))
{
throw new IOException(strReply.Substring(4));
} //int byteYu = (int)size % 512;
//int byteChu = (int)size / 512;
//byte[] tempBuffer = new byte[byteYu];
//for (int i = 0; i < byteChu; i++)
//{
// socketData.Receive(buffer, buffer.Length, 0);
//} //socketData.Receive(tempBuffer, tempBuffer.Length, 0); //socketData.Receive(buffer, byteYu, 0);
while (true)
{
int iBytes = socketData.Receive(buffer, buffer.Length, 0);
//totalBytes += iBytes; output.Write(buffer, 0, iBytes);
if (iBytes <= 0)
{
break;
}
}
output.Close();
if (socketData.Connected)
{
socketData.Close();
}
if (!(iReplyCode == 226 || iReplyCode == 250))
{
ReadReply();
if (!(iReplyCode == 226 || iReplyCode == 250))
{
throw new IOException(strReply.Substring(4));
}
}
} /// <summary>
/// 上传一批文件
/// </summary>
/// <param name="strFolder">本地目录(不得以\结束)</param>
/// <param name="strFileNameMask">文件名匹配字符(可以包含*和?)</param>
public void Put(string strFolder, string strFileNameMask)
{
string[] strFiles = Directory.GetFiles(strFolder, strFileNameMask);
foreach (string strFile in strFiles)
{
//strFile是完整的文件名(包含路径)
Put(strFile);
}
} /// <summary>
/// 上传一个文件
/// </summary>
/// <param name="strFileName">本地文件名</param>
public void Put(string strFileName)
{
bool isok = false;
try
{
if (!bConnected)
{
Connect();
}
Socket socketData = CreateDataSocket();
SendCommand("STOR " + Path.GetFileName(strFileName));
if (!(iReplyCode == 125 || iReplyCode == 150))
{
throw new IOException(strReply.Substring(4));
}
FileStream input = new
FileStream(strFileName, FileMode.Open);
int iBytes = 0;
while ((iBytes = input.Read(buffer, 0, buffer.Length)) > 0)
{
socketData.Send(buffer, iBytes, 0);
}
input.Close();
if (socketData.Connected)
{
socketData.Close();
}
if (!(iReplyCode == 226 || iReplyCode == 250))
{
ReadReply();
if (!(iReplyCode == 226 || iReplyCode == 250))
{
throw new IOException(strReply.Substring(4));
}
}
isok = true;
}
catch (Exception ex)
{ ex.Message.ToString(); }
}
/// <summary>
///
/// </summary>
/// <param name="strFileName"></param>
public bool Putload(string strFileName)
{
bool isok = false;
try
{
if (!bConnected)
{
Connect();
}
Socket socketData = CreateDataSocket();
SendCommand("STOR " + Path.GetFileName(strFileName));
if (!(iReplyCode == 125 || iReplyCode == 150))
{
throw new IOException(strReply.Substring(4));
}
FileStream input = new
FileStream(strFileName, FileMode.Open);
int iBytes = 0;
while ((iBytes = input.Read(buffer, 0, buffer.Length)) > 0)
{
socketData.Send(buffer, iBytes, 0);
}
input.Close();
if (socketData.Connected)
{
socketData.Close();
}
if (!(iReplyCode == 226 || iReplyCode == 250))
{
ReadReply();
if (!(iReplyCode == 226 || iReplyCode == 250))
{
throw new IOException(strReply.Substring(4));
}
}
isok = true;
}
catch (Exception ex)
{ ex.Message.ToString(); }
return isok;
}
#endregion #region 目录操作
/// <summary>
/// 创建目录
/// </summary>
/// <param name="strDirName">目录名</param>
public void MkDir(string strDirName)
{
if (!bConnected)
{
Connect();
}
SendCommand("MKD " + strDirName);
if (iReplyCode != 257)
{
throw new IOException(strReply.Substring(4));
}
} /// <summary>
/// 删除目录
/// </summary>
/// <param name="strDirName">目录名</param>
public void RmDir(string strDirName)
{
if (!bConnected)
{
Connect();
}
SendCommand("RMD " + strDirName);
if (iReplyCode != 250)
{
throw new IOException(strReply.Substring(4));
}
} /// <summary>
/// 改变目录
/// </summary>
/// <param name="strDirName">新的工作目录名</param>
public void ChDir(string strDirName)
{
if (strDirName.Equals(".") || strDirName.Equals(""))
{
return;
}
if (!bConnected)
{
Connect();
}
SendCommand("CWD " + strDirName);
if (iReplyCode != 250)
{
throw new IOException(strReply.Substring(4));
}
this.strRemotePath = strDirName;
} #endregion #region 内部变量
/// <summary>
/// 服务器返回的应答信息(包含应答码)
/// </summary>
private string strMsg;
/// <summary>
/// 服务器返回的应答信息(包含应答码)
/// </summary>
private string strReply;
/// <summary>
/// 服务器返回的应答码
/// </summary>
private int iReplyCode;
/// <summary>
/// 进行控制连接的socket
/// </summary>
private Socket socketControl;
/// <summary>
/// 传输模式
/// </summary>
private TransferType trType;
/// <summary>
/// 接收和发送数据的缓冲区
/// </summary>
private static int BLOCK_SIZE = 512;
Byte[] buffer = new Byte[BLOCK_SIZE];
/// <summary>
/// 编码方式(为防止出现中文乱码采用 GB2312编码方式)
/// </summary>
Encoding GB2312 = Encoding.GetEncoding("gb2312");
#endregion #region 内部函数
/// <summary>
/// 将一行应答字符串记录在strReply和strMsg
/// 应答码记录在iReplyCode
/// </summary>
private void ReadReply()
{
strMsg = "";
strReply = ReadLine();
iReplyCode = Int32.Parse(strReply.Substring(0, 3));
} /// <summary>
/// 建立进行数据连接的socket
/// </summary>
/// <returns>数据连接socket</returns>
private Socket CreateDataSocket()
{
SendCommand("PASV");
if (iReplyCode != 227)
{
throw new IOException(strReply.Substring(4));
}
int index1 = strReply.IndexOf('(');
int index2 = strReply.IndexOf(')');
string ipData =
strReply.Substring(index1 + 1, index2 - index1 - 1);
int[] parts = new int[6];
int len = ipData.Length;
int partCount = 0;
string buf = "";
for (int i = 0; i < len && partCount <= 6; i++)
{
char ch = Char.Parse(ipData.Substring(i, 1));
if (Char.IsDigit(ch))
buf += ch;
else if (ch != ',')
{
throw new IOException("Malformed PASV strReply: " +
strReply);
}
if (ch == ',' || i + 1 == len)
{
try
{
parts[partCount++] = Int32.Parse(buf);
buf = "";
}
catch (Exception)
{
throw new IOException("Malformed PASV strReply: " +
strReply);
}
}
}
string ipAddress = parts[0] + "." + parts[1] + "." +
parts[2] + "." + parts[3];
int port = (parts[4] << 8) + parts[5];
Socket s = new
Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ep = new
IPEndPoint(IPAddress.Parse(ipAddress), port);
try
{
s.Connect(ep);
}
catch (Exception)
{
throw new IOException("Can't connect to remote server");
}
return s;
} /// <summary>
/// 关闭socket连接(用于登录以前)
/// </summary>
private void CloseSocketConnect()
{
if (socketControl != null)
{
socketControl.Close();
socketControl = null;
}
bConnected = false;
} /// <summary>
/// 读取Socket返回的所有字符串
/// </summary>
/// <returns>包含应答码的字符串行</returns>
private string ReadLine()
{
while (true)
{
int iBytes = socketControl.Receive(buffer, buffer.Length, 0);
strMsg += GB2312.GetString(buffer, 0, iBytes);
if (iBytes < buffer.Length)
{
break;
}
}
char[] seperator = { '\n' };
string[] mess = strMsg.Split(seperator);
if (strMsg.Length > 2)
{
strMsg = mess[mess.Length - 2];
//seperator[0]是10,换行符是由13和0组成的,分隔后10后面虽没有字符串,
//但也会分配为空字符串给后面(也是最后一个)字符串数组,
//所以最后一个mess是没用的空字符串
//但为什么不直接取mess[0],因为只有最后一行字符串应答码与信息之间有空格
}
else
{
strMsg = mess[0];
}
if (!strMsg.Substring(3, 1).Equals(" "))//返回字符串正确的是以应答码(如220开头,后面接一空格,再接问候字符串)
{
return ReadLine();
}
return strMsg;
} /// <summary>
/// 发送命令并获取应答码和最后一行应答字符串
/// </summary>
/// <param name="strCommand">命令</param>
private void SendCommand(String strCommand)
{
Byte[] cmdBytes =
GB2312.GetBytes((strCommand + "\r\n").ToCharArray());
socketControl.Send(cmdBytes, cmdBytes.Length, 0);
ReadReply();
} #endregion
}
}
测试:
/// <summary>
/// 下载文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
FTPClient client = new FTPClient(ftpServer, "/", user, pwd, int.Parse(port));
client.Connect();
GetFolder("*", remotingFolder, client, CreateFolder());
client.DisConnect();
ClearFolder();
MessageBox.Show("下载完毕");
System.Threading.Thread.Sleep(3000);
} /// <summary>
/// 在本地目录下创建一个以日期为名称的目录,我做这个ftp的主要目的是为了每天都备份
/// </summary>
/// <returns>创建的目录名</returns>
private string CreateFolder()
{
string folder = localFolder + "\\" + DateTime.Now.ToShortDateString();
if (!Directory.Exists(folder))
Directory.CreateDirectory(folder); return folder;
} /// <summary>
/// 在下载结束后清空程序目录的多余文件
/// </summary>
private void ClearFolder()
{
string folder = Environment.CurrentDirectory;
string[] dictorys = Directory.GetFiles(folder);
foreach (string dictory in dictorys)
{
FileInfo info = new FileInfo(dictory);
if (info.Length == 0)
File.Delete(dictory);
}
} /// <summary>
/// 递归获取ftp文件夹的内容
/// </summary>
/// <param name="fileMark">文件标记</param>
/// <param name="path">远程路径</param>
/// <param name="client"></param>
/// <param name="folder"></param>
private void GetFolder(string fileMark, string path, FTPClient client, string folder)
{
string[] dirs = client.Dir(path); //获取目录下的内容
client.ChDir(path); //改变目录
foreach (string dir in dirs)
{
string[] infos = dir.Split(' ');
string info = infos[infos.Length - 1].Replace("\r", "");
if (dir.StartsWith("d") && !string.IsNullOrEmpty(dir)) //为目录
{ if (!info.EndsWith(".") && !info.EndsWith("..")) //筛选出真实的目录
{
Directory.CreateDirectory(folder + "\\" + info);
GetFolder(fileMark, path + "/" + info, client, folder + "\\" + info);
client.ChDir(path);
}
}
else if (dir.StartsWith("-r")) //为文件
{
string file = folder + "\\" + info;
if (File.Exists(file))
{
long remotingSize = client.GetFileSize(info);
FileInfo fileInfo = new FileInfo(file);
long localSize = fileInfo.Length; if (remotingSize != localSize) //短点续传
{
client.GetBrokenFile(info, folder, info, localSize);
}
}
else
{
client.GetFile(info, folder, info); //下载文件
MessageBox.Show("文件" + folder + info + "已经下载");
}
}
} }
/// <summary>
/// 上传文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
try
{ OpenFileDialog op = new OpenFileDialog();
op.InitialDirectory = Application.StartupPath;
op.RestoreDirectory = true;
op.Filter = "压缩文件(*.zip)|*.zip|压缩文件(*.rar)|*.rar|所有文件(*.*)|*.*";
if (op.ShowDialog() == DialogResult.OK)
{
string aa = op.FileName; //上传在根目录下
//FTPClient client = new FTPClient(ftpServer, "/", user, pwd, int.Parse(port));
//client.Connect();
//client.Put(@"C:\nltk_data\tokenizers\punkt.zip");
//System.Threading.Thread.Sleep(3000); //上传在根目录下
FTPClient client = new FTPClient(ftpServer, "/", user, pwd, int.Parse(port));
client.Connect();
bool isok = client.Putload(aa);
System.Threading.Thread.Sleep(3000); //FileUpDownload.FtpServerIP = ftpServer;
//FileUpDownload.FtpUserID = user;
//FileUpDownload.FtpPassword = pwd;
//全路径
// bool isok = FileUpDownload.FtpUploadFile(aa); //上传成功 //在根目录下 //
//bool isok = Upload(aa); //在根目录下 if (isok)
{
MessageBox.Show("OK!");
}
} }
catch (Exception ex)
{
MessageBox.Show("erro");
} } /// <summary>
/// Method to upload the specified file to the specified FTP Server
/// </summary>
/// <param name="filename">file full name to be uploaded</param>
private bool Upload(string filename)
{
bool isok = false;
FileInfo fileInf = new FileInfo(filename);
string uri = "ftp://" + ftpServer + "/" + fileInf.Name; //+ localFolder +
FtpWebRequest reqFTP; // Create FtpWebRequest object from the Uri provided
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServer + "/" + fileInf.Name));//+ localFolder + "/" // Provide the WebPermission Credintials
reqFTP.Credentials = new NetworkCredential(user, pwd); // By default KeepAlive is true, where the control connection is not closed
// after a command is executed.
reqFTP.KeepAlive = false; // Specify the command to be executed.
reqFTP.Method = WebRequestMethods.Ftp.UploadFile; // Specify the data transfer type.
reqFTP.UseBinary = true; // Notify the server about the size of the uploaded file
reqFTP.ContentLength = fileInf.Length; // The buffer size is set to 2kb
int buffLength = 2048;
byte[] buff = new byte[buffLength];
int contentLen; // Opens a file stream (System.IO.FileStream) to read the file to be uploaded
FileStream fs = fileInf.OpenRead(); try
{
// Stream to which the file to be upload is written
Stream strm = reqFTP.GetRequestStream(); // Read from the file stream 2kb at a time
contentLen = fs.Read(buff, 0, buffLength); // Till Stream content ends
while (contentLen != 0)
{
// Write Content from the file stream to the FTP Upload Stream
strm.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
} // Close the file stream and the Request Stream
isok = true;
strm.Close();
fs.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Upload Error");
}
return isok;
}
/// <summary>
/// ftp帮助类
/// </summary>
public class FtpHelper
{
private string ftpHostIP { get; set; }
private string username { get; set; }
private string password { get; set; }
private string ftpURI { get { return string.Format("ftp://{0}/", ftpHostIP); } } /// <summary>
/// 初始化ftp参数
/// </summary>
/// <param name="ftpHostIP">ftp主机IP</param>
/// <param name="username">ftp账户</param>
/// <param name="password">ftp密码</param>
public FtpHelper(string ftpHostIP, string username, string password)
{
this.ftpHostIP = ftpHostIP;
this.username = username;
this.password = password;
} /// <summary>
/// 异常方法委托,通过Lamda委托统一处理异常,方便改写
/// </summary>
/// <param name="method">当前执行的方法</param>
/// <param name="action"></param>
/// <returns></returns>
private bool MethodInvoke(string method, Action action)
{
if (action != null)
{
try
{
action();
//Logger.Write2File($@"FtpHelper.{method}:执行成功");
//FluentConsole.Magenta.Line($@"FtpHelper({ftpHostIP},{username},{password}).{method}:执行成功");
return true;
}
catch (Exception ex)
{
//FluentConsole.Red.Line($@"FtpHelper({ftpHostIP},{username},{password}).{method}:执行失败:\n {ex}");
// Logger.Write2File(FtpHelper({ftpHostIP},{username},{password}).{method}:执行失败 \r\n{ex}");
return false;
}
}
else
{
return false;
}
} /// <summary>
/// 异常方法委托,通过Lamda委托统一处理异常,方便改写
/// </summary>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="method"></param>
/// <param name="func"></param>
/// <returns></returns>
private T MethodInvoke<T>(string method, Func<T> func)
{
if (func != null)
{
try
{
//FluentConsole.Magenta.Line($@"FtpHelper({ftpHostIP},{username},{password}).{method}:执行成功");
//Logger.Write2File($@"FtpHelper({ftpHostIP},{username},{password}).{method}:执行成功");
return func();
}
catch (Exception ex)
{
//FluentConsole.Red.Line($@"FtpHelper({ftpHostIP},{username},{password}).{method}:执行失败:").Line(ex);
// Logger.Write2File($@"FtpHelper({ftpHostIP},{username},{password}).{method}:执行失败 \r\n{ex}");
return default(T);
}
}
else
{
return default(T);
}
}
/// <summary>
/// https://stackoverflow.com/questions/17451620/reusing-ftpwebrequest
/// </summary>
/// <param name="URI"></param>
/// <returns></returns>
private FtpWebRequest GetRequest(string URI)
{
//根据服务器信息FtpWebRequest创建类的对象
FtpWebRequest result = (FtpWebRequest)WebRequest.Create(URI); //result.Credentials = new NetworkCredential(username, password); result.Method = WebRequestMethods.Ftp.GetFileSize;
NetworkCredential nc = new NetworkCredential(username, password);
result.Credentials = nc; //result.UseBinary = true;
//result.UsePassive = true;
//result.KeepAlive = true; result.KeepAlive = false;
result.UsePassive = false;
result.UseBinary = true; return result;
} /// <summary> 上传文件</summary>
/// <param name="filePath">需要上传的文件路径</param>
/// <param name="dirName">目标路径</param>
public bool UploadFile(string filePath, string dirName = "")
{
FileInfo fileInfo = new FileInfo(filePath);
if (dirName != "")
{
//if(DirectoryExist(dirName)
MakeDir(dirName);//检查文件目录,不存在就自动创建
} string uri =ftpURI+dirName;// Path.Combine(ftpURI, dirName, fileInfo.Name);
return MethodInvoke(@"uploadFile({filePath},{dirName})", () =>
{
FtpWebRequest ftp = GetRequest(uri);
ftp.Method = WebRequestMethods.Ftp.UploadFile;
ftp.ContentLength = fileInfo.Length;
int buffLength = 2048;
byte[] buff = new byte[buffLength];
int contentLen;
using (FileStream fs = fileInfo.OpenRead())
{
using (Stream strm = ftp.GetRequestStream())
{
contentLen = fs.Read(buff, 0, buffLength);
while (contentLen != 0)
{
strm.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
}
strm.Close();
}
fs.Close();
}
});
} /// <summary>
/// 从一个目录将其内容复制到另一目录
/// </summary>
/// <param name="localDir">源目录</param>
/// <param name="DirName">目标目录</param>
public void UploadAllFile(string localDir, string DirName = "")
{
string localDirName = string.Empty;
int targIndex = localDir.LastIndexOf("\\");
if (targIndex > -1 && targIndex != (localDir.IndexOf(":\\") + 1))
localDirName = localDir.Substring(0, targIndex);
localDirName = localDir.Substring(targIndex + 1);
string newDir = Path.Combine(DirName, localDirName);
MethodInvoke(@"UploadAllFile({localDir},{DirName})", () =>
{
MakeDir(newDir);
DirectoryInfo directoryInfo = new DirectoryInfo(localDir);
FileInfo[] files = directoryInfo.GetFiles();
//复制所有文件
foreach (FileInfo file in files)
{
UploadFile(file.FullName, newDir);
}
//最后复制目录
DirectoryInfo[] directoryInfoArray = directoryInfo.GetDirectories();
foreach (DirectoryInfo dir in directoryInfoArray)
{
UploadAllFile(Path.Combine(localDir, dir.Name), newDir);
}
});
} /// <summary>
/// 删除单个文件
/// </summary>
/// <param name="filePath"></param>
public bool DelFile(string filePath)
{
string uri = Path.Combine(ftpURI, filePath);
return MethodInvoke(@"DelFile({filePath})", () =>
{
FtpWebRequest ftp = GetRequest(uri);
ftp.Method = WebRequestMethods.Ftp.DeleteFile;
FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
response.Close();
});
} /// <summary>
/// 删除最末及空目录
/// </summary>
/// <param name="dirName"></param>
private bool DelDir(string dirName)
{
string uri = Path.Combine(ftpURI, dirName);
return MethodInvoke(@"DelDir({dirName})", () =>
{
FtpWebRequest ftp = GetRequest(uri);
ftp.Method = WebRequestMethods.Ftp.RemoveDirectory;
FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
response.Close();
});
} /// <summary> 删除目录或者其目录下所有的文件 </summary>
/// <param name="dirName">目录名称</param>
/// <param name="ifDelSub">是否删除目录下所有的文件</param>
public bool DelAll(string dirName)
{
var list = GetAllFtpFile(new List<ActFile>(),dirName);
if (list == null) return DelDir(dirName);
if (list.Count==0) return DelDir(dirName);//删除当前目录
var newlist = list.OrderByDescending(x => x.level);
foreach (var item in newlist)
{
//FluentConsole.Yellow.Line(@"level:{item.level},isDir:{item.isDir},path:{item.path}");
}
string uri = Path.Combine(ftpURI, dirName);
return MethodInvoke(@"DelAll({dirName})", () =>
{
foreach (var item in newlist)
{
if (item.isDir)//判断是目录调用目录的删除方法
DelDir(item.path);
else
DelFile(item.path);
}
DelDir(dirName);//删除当前目录
return true;
});
} /// <summary>
/// 下载单个文件
/// </summary>
/// <param name="ftpFilePath">从ftp要下载的文件路径</param>
/// <param name="localDir">下载至本地路径</param>
/// <param name="filename">文件名</param>
public bool DownloadFile(string ftpFilePath, string saveDir)
{
string filename = ftpFilePath.Substring(ftpFilePath.LastIndexOf("\\") + 1);
string tmpname = Guid.NewGuid().ToString();
string uri = ftpURI+ftpFilePath;//Path.Combine(ftpURI, ftpFilePath);//
return MethodInvoke(@"DownloadFile({ftpFilePath},{saveDir},{filename})", () =>
{
if (!Directory.Exists(saveDir)) Directory.CreateDirectory(saveDir);
FtpWebRequest ftp = GetRequest(uri);
ftp.Method = WebRequestMethods.Ftp.DownloadFile;
using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
using (FileStream fs = new FileStream(Path.Combine(saveDir, filename), FileMode.CreateNew)) //Path.Combine(saveDir, filename)
{
byte[] buffer = new byte[2048];
int read = 0;
do
{
read = responseStream.Read(buffer, 0, buffer.Length);
fs.Write(buffer, 0, read);
} while (!(read == 0));
responseStream.Close();
fs.Flush();
fs.Close();
}
responseStream.Close();
}
response.Close();
}
});
} /// <summary>
/// 从FTP下载整个文件夹
/// </summary>
/// <param name="dirName">FTP文件夹路径</param>
/// <param name="saveDir">保存的本地文件夹路径</param>
public void DownloadAllFile(string dirName, string saveDir)
{
MethodInvoke(@"DownloadAllFile({dirName},{saveDir})", () =>
{
List<ActFile> files = GetFtpFile(dirName);
if (!Directory.Exists(saveDir))
{
Directory.CreateDirectory(saveDir);
}
foreach (var f in files)
{
if (f.isDir) //文件夹,递归查询
{
DownloadAllFile(Path.Combine(dirName,f.name), Path.Combine(saveDir ,f.name));
}
else //文件,直接下载
{
DownloadFile(Path.Combine(dirName,f.name), saveDir);
}
}
});
} /// <summary>
/// 获取当前目录下的目录及文件
/// </summary>
/// param name="ftpfileList"></param>
/// <param name="dirName"></param>
/// <returns></returns>
public List<ActFile> GetFtpFile(string dirName,int ilevel = 0)
{
var ftpfileList = new List<ActFile>();
string uri = Path.Combine(ftpURI, dirName);
return MethodInvoke(@"GetFtpFile({dirName})", () =>
{
var a = new List<List<string>>();
FtpWebRequest ftp = GetRequest(uri);
ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
Stream stream = ftp.GetResponse().GetResponseStream();
using (StreamReader sr = new StreamReader(stream))
{
string line = sr.ReadLine();
while (!string.IsNullOrEmpty(line))
{
ftpfileList.Add(new ActFile { isDir = line.IndexOf("<DIR>") > -1, name = line.Substring(39).Trim(), path = Path.Combine(dirName, line.Substring(39).Trim()), level= ilevel });
line = sr.ReadLine();
}
sr.Close();
}
return ftpfileList;
}); } /// <summary>
/// 获取FTP目录下的所有目录及文件包括其子目录和子文件
/// </summary>
/// param name="result"></param>
/// <param name="dirName"></param>
/// <returns></returns>
public List<ActFile> GetAllFtpFile(List<ActFile> result,string dirName, int level = 0)
{
var ftpfileList = new List<ActFile>();
string uri = Path.Combine(ftpURI, dirName);
return MethodInvoke(@"GetAllFtpFile({dirName})", () =>
{
ftpfileList = GetFtpFile(dirName, level);
result.AddRange(ftpfileList);
var newlist = ftpfileList.Where(x => x.isDir).ToList();
foreach (var item in newlist)
{
GetAllFtpFile(result,item.path, level+1);
}
return result;
}); } /// <summary>
/// 检查目录是否存在
/// </summary>
/// <param name="dirName"></param>
/// <param name="currentDir"></param>
/// <returns></returns>
public bool CheckDir(string dirName, string currentDir) // = ""
{
string uri = ftpURI+currentDir; //Path.Combine(ftpURI, currentDir);
if (!string.IsNullOrEmpty(currentDir))
{
return MethodInvoke(@"CheckDir({dirName}{currentDir})", () =>
{
FtpWebRequest ftp = GetRequest(uri);
ftp.UseBinary = true;
ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails; //获取FTP目录下所有的文件和文件夹的名字
// WebRequestMethods.Ftp.ListDirectory;
Stream stream = ftp.GetResponse().GetResponseStream();
using (StreamReader sr = new StreamReader(stream))
{
string line = sr.ReadLine();
while (!string.IsNullOrEmpty(line))
{
if (line.IndexOf("<DIR>") > -1)
{
if (line.Substring(39).Trim() == dirName)
return true;
}
line = sr.ReadLine();
}
sr.Close();
}
stream.Close();
return false;
});
}
else
{
return false;
} } /// </summary>
/// 在ftp服务器上创建指定目录,父目录不存在则创建
/// </summary>
/// <param name="dirName">创建的目录名称</param>
public bool MakeDir(string dirName)
{
var dirs = dirName.Split('\\').ToList();//针对多级目录分割
string currentDir = string.Empty;
return MethodInvoke(@"MakeDir({dirName})", () =>
{
foreach (var dir in dirs)
{
//涂聚文 Geovin Du
//if (string.IsNullOrEmpty(dir))
//{
// continue;
//}
if (!string.IsNullOrEmpty(dir))
{
//存在问题,判断是文件夹,再判断是否存在此文件夹,不存在也创建
if (!dir.Contains(".")) //如果是文件不考虑
{
currentDir = currentDir + "/" + dir;//Path.Combine(currentDir, dir);
string uri = ftpURI + currentDir;// Path.Combine(ftpURI, currentDir);
if (!DirectoryExist(uri))//检查目录不存在则创建CheckDir(dir, currentDir) //要考虑不是文件,是文件夹。
{
FtpWebRequest ftp = GetRequest(uri);
ftp.Method = WebRequestMethods.Ftp.MakeDirectory; //无权限
FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
response.Close();
}
}
}
} }); }
/// <summary>
/// 文件夹是否存在
/// </summary>
/// <param name="URI"></param>
/// <returns></returns>
public bool DirectoryExist(string uri)
{ FtpWebRequest reqFTP = GetRequest(uri);
// FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
//reqFTP.Credentials = new NetworkCredential("", "");
reqFTP.Method = WebRequestMethods.Ftp.ListDirectory; //PrintWorkingDirectory ListDirectoryDetails
reqFTP.UseBinary = true;
try
{
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
string line = reader.ReadLine();
reader.Close();
response.Close();
if (line != null)
{
return true;
}
else
{
return false;
}
}
catch (Exception ex)
{
string e = ex.Message;
return false;
}
} /// <summary>
/// Normalizes the URI.
/// </summary>
/// <param name="uri">The URI.</param>
/// <returns>A normalized URI</returns>
private Uri NormalizeUri(Uri uri)
{
if (uri == null)
throw new ArgumentNullException("uri"); if (uri.Scheme != Uri.UriSchemeFtp)
throw new ArgumentException("The URI isn't a valid FTP URI", "uri"); string path = uri.AbsoluteUri; //Cut the "ftp://" off
path = path.Substring(6); path = path.Replace("//", "/").Replace(@"\\", "/").Replace(@"\", "/"); return new Uri("ftp://" + path);
}
/// <summary>文件重命名 </summary>
/// <param name="currentFilename">当前名称</param>
/// <param name="newFilename">重命名名称</param>
/// <param name="currentFilename">所在的目录</param>
public bool Rename(string currentFilename, string newFilename, string dirName = "")
{
string uri = Path.Combine(ftpURI, dirName, currentFilename);
return MethodInvoke(@"Rename({currentFilename},{newFilename},{dirName})", () =>
{
FtpWebRequest ftp = GetRequest(uri);
ftp.Method = WebRequestMethods.Ftp.Rename;
ftp.RenameTo = newFilename;
FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
response.Close();
});
}
}
/// <summary>
///
/// </summary>
public class ActFile
{
public int level { get; set; }
public bool isDir { get; set; }
public string name { get; set; }
public string path { get; set; }
}
测试:
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
var ftp = new FtpHelper(ftpServer, user, pwd);//初始化ftp,创建ftp对象 //ftp.DelAll("test");//删除ftptest目录及其目录下的所有文件
// ftp.UploadAllFile("F:\\涂聚文维修方案000.pdf");//上传单个文件到指定目录
//ftp.UploadAllFile("F:\\test");//将本地test目录的所有文件上传
// bool ok= ftp.DownloadFile(@"\htdocs\涂聚文维修方案.pdf", "F:\\");//下载单个目录
// ftp.DownloadAllFile("test", "F:\\test1");//批量下载整个目录
//ftp.MakeDir("aaa\\bbb\\ccc\\ddd");//创建多级目录 bool ok = ftp.UploadFile("F:\\涂聚文维修方案000.pdf", @"\htdocs\geovindu\涂聚文维修方案000.pdf"); //上传成功
if (ok)
{
MessageBox.Show("ok");
}
else
{
MessageBox.Show("no");
}
}
https://github.com/hgupta9/FluentFTP
https://fluentftp.codeplex.com/
测试示例:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Configuration;
using FluentFTP;
using System.Threading;
using System.Net; namespace FluentFtpDemo
{ /// <summary>
/// 涂聚文测试示例
/// Geovin Du
/// </summary>
public partial class Form1 : Form
{
string remotingFolder = System.Configuration.ConfigurationManager.AppSettings["remotingFolder"]; //远程ftp文件目录
string localFolder = System.Configuration.ConfigurationManager.AppSettings["localFolder"]; //要下载到的本地目录
string ftpServer = System.Configuration.ConfigurationManager.AppSettings["ftpServer"]; //ftp服务器
string user = System.Configuration.ConfigurationManager.AppSettings["user"]; //用户名
string pwd = System.Configuration.ConfigurationManager.AppSettings["pwd"]; //密码
string port = System.Configuration.ConfigurationManager.AppSettings["port"]; //端口
string remotingFolderOther = System.Configuration.ConfigurationManager.AppSettings["remotingFolderOther"]; static ManualResetEvent m_reset = new ManualResetEvent(false);
/// <summary>
///
/// </summary>
public Form1()
{
InitializeComponent();
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, EventArgs e)
{ }
/// <summary>
/// 判断文件夹是否存在
/// </summary>
public void BeginDirectoryExists()
{
// The using statement here is OK _only_ because m_reset.WaitOne()
// causes the code to block until the async process finishes, otherwise
// the connection object would be disposed early. In practice, you
// typically would not wrap the following code with a using statement.
using (FtpClient conn = new FtpClient())
{
m_reset.Reset(); conn.Host = ftpServer;
conn.Credentials = new NetworkCredential(user, pwd);
conn.BeginDirectoryExists("/htdocs/admin", new AsyncCallback(DirectoryExistsCallback), conn); m_reset.WaitOne();
conn.Disconnect();
}
}
/// <summary>
///
/// </summary>
/// <param name="ar"></param>
void DirectoryExistsCallback(IAsyncResult ar)
{
FtpClient conn = ar.AsyncState as FtpClient; try
{
if (conn == null)
throw new InvalidOperationException("The FtpControlConnection object is null!"); MessageBox.Show("Directory Exiss: " + conn.EndDirectoryExists(ar));
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
m_reset.Set();
}
}
/// <summary>
/// 文件是否存在
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{ BeginFileExists();
}
/// <summary>
/// 判断文件是否存在
/// </summary>
public void BeginFileExists()
{
// The using statement here is OK _only_ because m_reset.WaitOne()
// causes the code to block until the async process finishes, otherwise
// the connection object would be disposed early. In practice, you
// typically would not wrap the following code with a using statement.
using (FtpClient conn = new FtpClient())
{
m_reset.Reset();
conn.Encoding = Encoding.UTF8; //设置编码
conn.Host = ftpServer;
conn.Credentials = new NetworkCredential(user, pwd);
conn.Connect();
string file = (@"\htdocs\法律法规依据目录.pdf");
//中文文件名出问题
conn.BeginFileExists(file, new AsyncCallback(BeginFileExistsCallback), conn);//涂聚文维修方案.pdf m_reset.WaitOne();
conn.Disconnect();
}
}
/// <summary>
///
/// </summary>
/// <param name="ar"></param>
void BeginFileExistsCallback(IAsyncResult ar)
{
FtpClient conn = ar.AsyncState as FtpClient; try
{
if (conn == null)
throw new InvalidOperationException("The FtpControlConnection object is null!"); MessageBox.Show("File exists: " + conn.EndFileExists(ar));
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
m_reset.Set();
}
} /// <summary>
/// GB2312转换成UTF8
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public static string gb2312_utf8(string text)
{
//声明字符集
System.Text.Encoding utf8, gb2312;
//gb2312
gb2312 = System.Text.Encoding.GetEncoding("gb2312");
//utf8
utf8 = System.Text.Encoding.GetEncoding("utf-8");
byte[] gb;
gb = gb2312.GetBytes(text);
gb = System.Text.Encoding.Convert(gb2312, utf8, gb);
//返回转换后的字符
return utf8.GetString(gb);
} /// <summary>
/// UTF8转换成GB2312
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public static string utf8_gb2312(string text)
{
//声明字符集
System.Text.Encoding utf8, gb2312;
//utf8
utf8 = System.Text.Encoding.GetEncoding("utf-8");
//gb2312
gb2312 = System.Text.Encoding.GetEncoding("gb2312");
byte[] utf;
utf = utf8.GetBytes(text);
utf = System.Text.Encoding.Convert(utf8, gb2312, utf);
//返回转换后的字符
return gb2312.GetString(utf);
}
/// <summary>
/// 文件夹是否存在
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
BeginDirectoryExists();
}
/// <summary>
/// 创建文件夹
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e)
{
BeginCreateDirectory();
}
/// <summary>
/// 创建文件夹
/// </summary>
public void BeginCreateDirectory()
{
// The using statement here is OK _only_ because m_reset.WaitOne()
// causes the code to block until the async process finishes, otherwise
// the connection object would be disposed early. In practice, you
// typically would not wrap the following code with a using statement.
using (FtpClient conn = new FtpClient())
{
m_reset.Reset(); conn.Host = ftpServer;
conn.Encoding = Encoding.UTF8;
conn.Credentials = new NetworkCredential(user, pwd);
// conn.DeleteDirectory("/test");
conn.BeginCreateDirectory("/htdocs/geovindu/created", true,new AsyncCallback(CreateDirectoryCallback), conn);
m_reset.WaitOne();
conn.Disconnect();
}
}
/// <summary>
///
/// </summary>
/// <param name="ar"></param>
void CreateDirectoryCallback(IAsyncResult ar)
{
FtpClient conn = ar.AsyncState as FtpClient; try
{
if (conn == null)
throw new InvalidOperationException("The FtpControlConnection object is null!"); conn.EndCreateDirectory(ar);
MessageBox.Show("创建成功!");
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
m_reset.Set();
}
}
/// <summary>
/// 删除文件夹
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button4_Click(object sender, EventArgs e)
{
BeginDeleteDirectory();
}
/// <summary>
///
/// </summary>
public void BeginDeleteDirectory()
{
// The using statement here is OK _only_ because m_reset.WaitOne()
// causes the code to block until the async process finishes, otherwise
// the connection object would be disposed early. In practice, you
// typically would not wrap the following code with a using statement.
using (FtpClient conn = new FtpClient())
{
m_reset.Reset();
conn.Host = ftpServer;
conn.Encoding = Encoding.UTF8;
conn.Credentials = new NetworkCredential(user, pwd);
//conn.CreateDirectory("/some/test/directory");
conn.BeginDeleteDirectory("/htdocs/geovindu", new AsyncCallback(DeleteDirectoryCallback), conn);
m_reset.WaitOne();
conn.Disconnect();
}
} /// <summary>
///
/// </summary>
/// <param name="ar"></param>
void DeleteDirectoryCallback(IAsyncResult ar)
{
FtpClient conn = ar.AsyncState as FtpClient; try
{
if (conn == null)
throw new InvalidOperationException("The FtpControlConnection object is null!"); conn.EndDeleteDirectory(ar);
MessageBox.Show("删除成功");
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
m_reset.Set();
}
}
}
}
csharp:FTP Client Library using FtpWebRequest or Sockets的更多相关文章
- csharp: FTP Client Library using System.Net.FtpWebRequest
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...
- csharp: FTP Client Library using System.Net.FtpClient and FluentFTP,测试中存在的BUG修正
https://netftp.codeplex.com/ /// <summary> /// Gets a file listing from the server. Each FtpLi ...
- 分布式缓存系统Memcached简介与实践(.NET memcached client library)
缘起: 在数据驱动的web开发中,经常要重复从数据库中取出相同的数据,这种重复极大的增加了数据库负载.缓存是解决这个问题的好办法.但是ASP.NET中的虽然已经可以实现对页面局部进行缓存,但还是不够灵 ...
- C# Ftp Client 基本操作
C# Ftp Client 上传.下载与删除 简单介绍一下Ftp Client 上传.下载与删除,这是目前比较常用的命令,各个方法其实都差不多,重点是了解Ftp命令协议. 1.建立连接 public ...
- Ubuntu Filezilla FTP Client 安装
/************************************************************************************* * Ubuntu File ...
- 谷歌正式发布Google APIs Client Library for .NET
好消息,特大好消息! 英文原文:Google API library for .NET paves the way for Google services on Windows phone 本月 17 ...
- Memcached通用类(基于Memcached Client Library)
分享下自己编写的Memcached通用类.欢迎大家帮忙指点下哈~ 使用的是.NET memcached client library 客户端+Memcached Providers using Sys ...
- 使用 FileZilla FTP Client连接Vsftpd在执行LIST命令后提示连接超时
使用 FileZilla FTP Client 连接 Vsftpd在执行LIST命令后提示连接超时. vi /etc/vsftpd/vsftpd.conf 添加: #开启被动模式 pasv_enabl ...
- Getting Started(Google Cloud Storage Client Library)
在运行下面的步骤之前,请确保: 1.你的项目已经激活了Google Cloud Storage和App Engine,包括已经创建了至少一个Cloud Storage bucket. 2.你已经下载了 ...
随机推荐
- 去除swagger ui的红色 error 错误提示
去除swagger ui的红色 error 错误提示 自定义js文件中加入以下的代码. 加入自定义的js方法看这里 http://www.cnblogs.com/wang2650/archive/20 ...
- Windows核心编程:第1章 错误处理
Github https://github.com/gongluck/Windows-Core-Program.git //第1章 错误处理.cpp: 定义应用程序的入口点. // #include ...
- Android Studio 配置 androidAnnotations框架详细步骤
第一步:打开app的build.gradle文件 第二步:添加下面红色的部分 apply plugin: 'com.android.application' android { compileSdkV ...
- MANIFEST.MF文件详解
1. 依赖包是否在classpath中: 2. 资源文件目录是否在classpath中: 3. 主类是否正确: 具体配置参考 maven-jar-plugin 配置 <plugin> &l ...
- speex与webrtc回声消除小结
回声消除AEC包含: 延时估计对齐+线性自适应滤波器+NLP(双讲检测.处理)+舒适噪声CNG 一.speex aec 1.没有NLP 2.只考虑实时DSP系统,即是没有延时对齐等 3.自适应滤波 ...
- Python函数——命名空间与闭包
前言 执行以下代码 def my_test(): x = 1 y = x+1 print(x) >> Traceback (most recent call last): File &qu ...
- Python基础教程(第3版) 笔记(三)
1.9.1让脚本像普通程序一样在UNIX中运行脚本,只需将下面的代码作为脚本的第一行, 就可在UNIX中轻松运行脚本: #!/usr/bin/env python 要像普通程序一样运行脚本,还必须将其 ...
- 如何理解 Linux 中的 load averages
原文:https://mp.weixin.qq.com/s?src=11×tamp=1533697106&ver=1047&signature=poqrJFfcNAB ...
- PHP-CPP开发扩展(一)
PHP-CPP是一个用于开发PHP扩展的C++库.PHP-CPP提供了一系列完善的文档.易于使用和扩展的类,让你可以相对快速的创建PHP的原生扩展. 为什么使用PHP-CPP 很快 用C++编写的代码 ...
- IDEA中SpringBoot项目快速创建单元测试
如何在IDEA中对于SpringBoot项目快速创建单元测试 创建测试用例 右键需要进行测试的方法,选择GO TO然后选择Test 点击Create New Test 勾选需要创建单元测试的方法 然后 ...