https://netftp.codeplex.com/SourceControl/latest http://ftplib.codeplex.com/ https://www.codeproject.com/articles/18537/c-ftp-client-library https://w ...
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[]