using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Collections;
using Microsoft.VisualBasic;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Forms;
//https://www.codeproject.com/Articles/56321/A-Windows-FTP-Application
//https://www.codeproject.com/Articles/4472/Enhanced-BrowseForFolder-styled-TreeView
//https://github.com/ChrisRichner/TreeViewFolderBrowser
//https://www.codeproject.com/Articles/11991/An-FTP-client-library-for-NET
//https://github.com/aybe/Windows-API-Code-Pack-1.1
//https://github.com/dbarros/WindowsAPICodePack namespace FTPLibrary
{
#region "FTP client class"
/// <summary>
/// A wrapper class for .NET 2.0 FTP
/// </summary>
/// <remarks>
/// This class does not hold open an FTP connection but
/// instead is stateless: for each FTP request it
/// connects, performs the request and disconnects.
/// </remarks>
public class FTPclient
{
#region Delegated & Events
//Download Progress Changed Event
public delegate void DownloadProgressChangedHandler(object sender, DownloadProgressChangedArgs e);
public event DownloadProgressChangedHandler OnDownloadProgressChanged; //Download Completed Event
public delegate void DownloadCompletedHandler(object sender, DownloadCompletedArgs e);
public event DownloadCompletedHandler OnDownloadCompleted; //New Server Message Event
public delegate void NewMessageHandler(object sender, NewMessageEventArgs e);
public event NewMessageHandler OnNewMessageReceived; //Upload Progress Changed Event
//Download Progress Changed Event
public delegate void UploadProgressChangedHandler(object sender, UploadProgressChangedArgs e);
public event UploadProgressChangedHandler OnUploadProgressChanged; //Upload Completed Event
public delegate void UploadCompletedHandler(object sender, UploadCompletedArgs e);
public event UploadCompletedHandler OnUploadCompleted;
#endregion #region "CONSTRUCTORS"
/// <summary>
/// Blank constructor
/// </summary>
/// <remarks>Hostname, username and password must be set manually</remarks>
public FTPclient()
{
} /// <summary>
/// Constructor just taking the hostname
/// </summary>
/// <param name="Hostname">in either ftp://ftp.host.com or ftp.host.com form</param>
/// <remarks></remarks>
public FTPclient(string Hostname)
{
_hostname = Hostname;
} /// <summary>
/// Constructor taking hostname, username and password
/// </summary>
/// <param name="Hostname">in either ftp://ftp.host.com or ftp.host.com form</param>
/// <param name="Username">Leave blank to use 'anonymous' but set password to your email</param>
/// <param name="Password"></param>
/// <remarks></remarks>
public FTPclient(string Hostname, string Username, string Password)
{
_hostname = Hostname;
_username = Username;
_password = Password;
}
#endregion #region "Directory functions"
/// <summary>
/// Return a simple directory listing
/// </summary>
/// <param name="directory">Directory to list, e.g. /pub</param>
/// <returns>A list of filenames and directories as a List(of String)</returns>
/// <remarks>For a detailed directory listing, use ListDirectoryDetail</remarks>
public List<string> ListDirectory(string directory)
{
//return a simple list of filenames in directory
System.Net.FtpWebRequest ftp = GetRequest(GetDirectory(directory));
//Set request to do simple list
ftp.Method = System.Net.WebRequestMethods.Ftp.ListDirectory;
//Give Message of Command
NewMessageEventArgs e = new NewMessageEventArgs("COMMAND", "List Directory", "NLST");
OnNewMessageReceived(this, e); string str = GetStringResponse(ftp);
//replace CRLF to CR, remove last instance
str = str.Replace("\r\n", "\r").TrimEnd('\r');
//split the string into a list
List<string> result = new List<string>();
result.AddRange(str.Split('\r'));
return result;
} /// <summary>
/// Return a detailed directory listing
/// </summary>
/// <param name="directory">Directory to list, e.g. /pub/etc</param>
/// <returns>An FTPDirectory object</returns>
public FTPdirectory ListDirectoryDetail(string directory)
{
System.Net.FtpWebRequest ftp = GetRequest(GetDirectory(directory));
//Set request to do simple list
ftp.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails;
ftp.UseBinary = true;
//Give Message of Command
NewMessageEventArgs e = new NewMessageEventArgs("COMMAND", "List Directory Details", "LIST");
OnNewMessageReceived(this, e);
string str = GetStringResponse(ftp);
//replace CRLF to CR, remove last instance
str = str.Replace("\r\n", "\r").TrimEnd('\r');
//split the string into a list
return new FTPdirectory(str, _lastDirectory);
} #endregion #region "Upload: File transfer TO ftp server"
/// <summary>
/// Copy a local file to the FTP server
/// </summary>
/// <param name="localFilename">Full path of the local file</param>
/// <param name="targetFilename">Target filename, if required</param>
/// <returns></returns>
/// <remarks>If the target filename is blank, the source filename is used
/// (assumes current directory). Otherwise use a filename to specify a name
/// or a full path and filename if required.</remarks>
public bool Upload(string localFilename, string targetFilename)
{
//1. check source
if (!File.Exists(localFilename))
{
throw (new ApplicationException("File " + localFilename + " not found"));
}
//copy to FI
FileInfo fi = new FileInfo(localFilename);
return Upload(fi, targetFilename);
} #region Upload Variables
System.Net.FtpWebRequest UploadFTPRequest = null;
FileStream UploadFileStream = null;
Stream UploadStream = null;
bool UploadCanceled = false;
FileInfo UploadFileInfo = null;
#endregion /// <summary>
/// Upload a local file to the FTP server
/// </summary>
/// <param name="fi">Source file</param>
/// <param name="targetFilename">Target filename (optional)</param>
/// <returns></returns>
public bool Upload(FileInfo fi, string targetFilename)
{
//copy the file specified to target file: target file can be full path or just filename (uses current dir) //1. check target
string target;
if (targetFilename.Trim() == "")
{
//Blank target: use source filename & current dir
target = this.CurrentDirectory + fi.Name;
}
else if (targetFilename.Contains("/"))
{
//If contains / treat as a full path
target = AdjustDir(targetFilename);
}
else
{
//otherwise treat as filename only, use current directory
target = CurrentDirectory + targetFilename;
} string URI = Hostname + target;
//perform copy
UploadFTPRequest = GetRequest(URI); //Set request to upload a file in binary
UploadFTPRequest.Method = System.Net.WebRequestMethods.Ftp.UploadFile;
UploadFTPRequest.UseBinary = true;
//Notify FTP of the expected size
UploadFTPRequest.ContentLength = fi.Length;
UploadFileInfo = fi; //create byte array to store: ensure at least 1 byte!
const int BufferSize = 2048;
byte[] content = new byte[BufferSize - 1 + 1];
int dataRead; //open file for reading
using (UploadFileStream = fi.OpenRead())
{
try
{
//open request to send
using (UploadStream = UploadFTPRequest.GetRequestStream())
{
//Give Message of Command
NewMessageEventArgs e = new NewMessageEventArgs("COMMAND", "Upload File", "STOR");
OnNewMessageReceived(this, e); //Get File Size
Int64 TotalBytesUploaded = 0;
Int64 FileSize = fi.Length;
do
{
if (UploadCanceled)
{
NewMessageEventArgs CancelMessage = new NewMessageEventArgs("RESPONSE", "Upload Canceled.", "CANCEL");
OnNewMessageReceived(this, CancelMessage);
UploadCanceled = false;
return false;
} dataRead = UploadFileStream.Read(content, 0, BufferSize);
UploadStream.Write(content, 0, dataRead);
TotalBytesUploaded += dataRead;
//Declare Event
UploadProgressChangedArgs DownloadProgress = new UploadProgressChangedArgs(TotalBytesUploaded, FileSize); //Progress changed, Raise the event.
OnUploadProgressChanged(this, DownloadProgress); System.Windows.Forms.Application.DoEvents();
} while (!(dataRead < BufferSize)); //Get Message and Raise Event
NewMessageEventArgs UPloadResponse = new NewMessageEventArgs("RESPONSE", "File Uploaded!", "STOR");
OnNewMessageReceived(this, UPloadResponse); //Declare Event
UploadCompletedArgs Args = new UploadCompletedArgs("Successful", true);
//Raise Event
OnUploadCompleted(this, Args); UploadStream.Close();
} }
catch (Exception ex)
{
//Declare Event
UploadCompletedArgs Args = new UploadCompletedArgs("Error: " + ex.Message, false);
//Raise Event
OnUploadCompleted(this, Args);
}
finally
{
//ensure file closed
UploadFileStream.Close();
} } UploadFTPRequest = null;
return true; } public void CancelUpload(string UploadFileName)
{
if (UploadFileStream != null)
{
UploadFileStream.Close();
UploadFTPRequest.Abort();
//UploadFileInfo.Delete();
UploadCanceled = true;
UploadFTPRequest = null;
this.FtpDelete(UploadFileName);
MessageBox.Show("Upload Canceled");
}
}
#endregion #region "Download: File transfer FROM ftp server"
/// <summary>
/// Copy a file from FTP server to local
/// </summary>
/// <param name="sourceFilename">Target filename, if required</param>
/// <param name="localFilename">Full path of the local file</param>
/// <returns></returns>
/// <remarks>Target can be blank (use same filename), or just a filename
/// (assumes current directory) or a full path and filename</remarks>
public bool Download(string sourceFilename, string localFilename, bool PermitOverwrite)
{
//2. determine target file
FileInfo fi = new FileInfo(localFilename);
return this.Download(sourceFilename, fi, PermitOverwrite);
} //Version taking an FtpFileInfo
public bool Download(FTPfileInfo file, string localFilename, bool PermitOverwrite)
{
return this.Download(file.FullName, localFilename, PermitOverwrite);
} //Another version taking FtpFileInfo and FileInfo
public bool Download(FTPfileInfo file, FileInfo localFI, bool PermitOverwrite)
{
return this.Download(file.FullName, localFI, PermitOverwrite);
} #region Download Variables
System.Net.FtpWebRequest DownloadFTPRequest = null;
FtpWebResponse DownloadResponse = null;
Stream DownloadResponseStream = null; //中文亂碼
FileStream DownloadFileStream = null;
FileInfo TargetFileInfo = null;
bool DownloadCanceled = false;
#endregion
//Version taking string/FileInfo
public bool Download(string sourceFilename, FileInfo targetFI, bool PermitOverwrite)
{
//1. check target
if (targetFI.Exists && !(PermitOverwrite))
{
throw (new ApplicationException("Target file already exists"));
} //2. check source
string target;
if (sourceFilename.Trim() == "")
{
throw (new ApplicationException("File not specified"));
}
else if (sourceFilename.Contains("/"))
{
//treat as a full path
target = AdjustDir(sourceFilename);
}
else
{
//treat as filename only, use current directory
target = CurrentDirectory + sourceFilename;
} string URI = Hostname + target; //3. perform copy
DownloadFTPRequest = GetRequest(URI); //Set request to download a file in binary mode
DownloadFTPRequest.Method = System.Net.WebRequestMethods.Ftp.DownloadFile;
DownloadFTPRequest.UseBinary = true;
TargetFileInfo = targetFI;
//open request and get response stream
using (DownloadResponse = (FtpWebResponse)DownloadFTPRequest.GetResponse())
{
using (DownloadResponseStream = DownloadResponse.GetResponseStream())
{
//System.Security.AccessControl.FileSecurity fileSecurity = new System.Security.AccessControl.FileSecurity(targetFI.FullName, System.Security.AccessControl.AccessControlSections.All);
//targetFI.SetAccessControl(fileSecurity);
//loop to read & write to file
using (DownloadFileStream = new FileStream(targetFI.FullName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
try
{
//Give Message of Command
NewMessageEventArgs e = new NewMessageEventArgs("COMMAND", "Download File", "RETR");
OnNewMessageReceived(this, e);
byte[] buffer = new byte[2048];
int read = 0;
Int64 TotalBytesRead = 0;
Int64 FileSize = this.GetFileSize(sourceFilename);
DownloadCanceled = false;
do
{
if (DownloadCanceled)
{
NewMessageEventArgs CancelMessage = new NewMessageEventArgs("RESPONSE", "Download Canceled.", "CANCEL"); DownloadCanceled = false;
OnNewMessageReceived(this, CancelMessage);
return false;
} read = DownloadResponseStream.Read(buffer, 0, buffer.Length);
DownloadFileStream.Write(buffer, 0, read);
TotalBytesRead += read;
//Declare Event
DownloadProgressChangedArgs DownloadProgress = new DownloadProgressChangedArgs(TotalBytesRead, FileSize); //Progress changed, Raise the event.
OnDownloadProgressChanged(this, DownloadProgress); System.Windows.Forms.Application.DoEvents(); } while (!(read == 0)); //Get Message and Raise Event
NewMessageEventArgs NewMessageArgs = new NewMessageEventArgs("RESPONSE", DownloadResponse.StatusDescription, DownloadResponse.StatusCode.ToString());
OnNewMessageReceived(this, NewMessageArgs); //Declare Event
DownloadCompletedArgs Args = new DownloadCompletedArgs("Successful", true);
//Raise Event
OnDownloadCompleted(this, Args); DownloadResponseStream.Close();
DownloadFileStream.Flush();
DownloadFileStream.Close();
DownloadFileStream = null;
DownloadResponseStream = null;
}
catch (Exception ex)
{
//catch error and delete file only partially downloaded
DownloadFileStream.Close();
//delete target file as it's incomplete
targetFI.Delete(); //Decalre Event for Error
DownloadCompletedArgs DownloadCompleted = new DownloadCompletedArgs("Error: " + ex.Message, false);
//Raise Event
OnDownloadCompleted(this, DownloadCompleted);
}
}
if (DownloadFileStream != null)
DownloadResponseStream.Close();
}
if (DownloadFileStream != null)
DownloadResponse.Close();
}
return true;
} public void CancelDownload()
{
if (DownloadFileStream != null)
{
DownloadFileStream.Close(); DownloadFTPRequest.Abort(); DownloadResponse.Close();
DownloadResponseStream.Close();
//DownloadFileStream = null;
//DownloadResponseStream = null;
TargetFileInfo.Delete();
DownloadCanceled = true;
MessageBox.Show("Download Canceled");
}
}
#endregion #region "Other functions: Delete rename etc."
/// <summary>
/// Delete remote file
/// </summary>
/// <param name="filename">filename or full path</param>
/// <returns></returns>
/// <remarks></remarks>
public bool FtpDelete(string filename)
{
//Determine if file or full path
string URI = this.Hostname + GetFullPath(filename); System.Net.FtpWebRequest ftp = GetRequest(URI);
//Set request to delete
ftp.Method = System.Net.WebRequestMethods.Ftp.DeleteFile;
try
{
//get response but ignore it
string str = GetStringResponse(ftp);
//Give Message of Command
NewMessageEventArgs e = new NewMessageEventArgs("COMMAND", "Delete File", "DELE");
OnNewMessageReceived(this, e);
}
catch (Exception)
{
return false;
}
return true;
} /// <summary>
/// Determine if file exists on remote FTP site
/// </summary>
/// <param name="filename">Filename (for current dir) or full path</param>
/// <returns></returns>
/// <remarks>Note this only works for files</remarks>
public bool FtpFileExists(string filename)
{
//Try to obtain filesize: if we get error msg containing "550"
//the file does not exist
try
{
long size = GetFileSize(filename);
return true; }
catch (Exception ex)
{
//only handle expected not-found exception
if (ex is System.Net.WebException)
{
//file does not exist/no rights error = 550
if (ex.Message.Contains("550"))
{
//clear
return false;
}
else
{
System.Windows.Forms.MessageBox.Show(ex.Message);
return false;
}
}
else
{
System.Windows.Forms.MessageBox.Show(ex.Message);
return false;
}
}
} /// <summary>
/// Determine size of remote file
/// </summary>
/// <param name="filename"></param>
/// <returns></returns>
/// <remarks>Throws an exception if file does not exist</remarks>
public long GetFileSize(string filename)
{
string path;
if (filename.Contains("/"))
{
path = AdjustDir(filename);
}
else
{
path = this.CurrentDirectory + filename;
}
string URI = this.Hostname + path;
System.Net.FtpWebRequest ftp = GetRequest(URI);
//Try to get info on file/dir?
ftp.Method = System.Net.WebRequestMethods.Ftp.GetFileSize;
string tmp = this.GetStringResponse(ftp);
//Give Message of Command
NewMessageEventArgs e = new NewMessageEventArgs("COMMAND", "Get File Size", "SIZE");
OnNewMessageReceived(this, e);
return GetSize(ftp);
} public bool FtpRename(string sourceFilename, string newName)
{
//Does file exist?
string source = GetFullPath(sourceFilename);
if (!FtpFileExists(source))
{
throw (new FileNotFoundException("File " + source + " not found"));
} //build target name, ensure it does not exist
string target = GetFullPath(newName);
if (target == source)
{
throw (new ApplicationException("Source and target are the same"));
}
else if (FtpFileExists(target))
{
throw (new ApplicationException("Target file " + target + " already exists"));
} //perform rename
string URI = this.Hostname + source; System.Net.FtpWebRequest ftp = GetRequest(URI);
//Set request to delete
ftp.Method = System.Net.WebRequestMethods.Ftp.Rename;
ftp.RenameTo = target;
ftp.UseBinary = true; try
{
//get response but ignore it
string str = GetStringResponse(ftp);
//Give Message of Command
NewMessageEventArgs e = new NewMessageEventArgs("COMMAND", "File Rename", "RENAME");
OnNewMessageReceived(this, e);
}
catch (Exception)
{
return false;
}
return true;
} public bool FtpCreateDirectory(string dirpath)
{
//perform create
string URI = this.Hostname + AdjustDir(dirpath);
System.Net.FtpWebRequest ftp = GetRequest(URI);
//Set request to MkDir
ftp.Method = System.Net.WebRequestMethods.Ftp.MakeDirectory;
try
{
//get response but ignore it
string str = GetStringResponse(ftp);
//Give Message of Command
NewMessageEventArgs e = new NewMessageEventArgs("COMMAND", "Make Directory", "MKD");
OnNewMessageReceived(this, e);
}
catch (Exception)
{
return false;
}
return true;
} public bool FtpDeleteDirectory(string dirpath)
{
//perform remove
string URI = this.Hostname + AdjustDir(dirpath);
System.Net.FtpWebRequest ftp = GetRequest(URI);
ftp.UseBinary = true;
//Set request to RmDir
ftp.Method = System.Net.WebRequestMethods.Ftp.RemoveDirectory;
try
{
//get response but ignore it
string str = GetStringResponse(ftp);
//Give Message of Command
NewMessageEventArgs e = new NewMessageEventArgs("COMMAND", "Remove Directory", "RMD");
OnNewMessageReceived(this, e);
}
catch (Exception)
{
return false;
}
return true;
}
#endregion #region "private supporting fns"
//Get the basic FtpWebRequest object with the
//common settings and security
private FtpWebRequest GetRequest(string URI)
{
//create request
FtpWebRequest result = (FtpWebRequest)FtpWebRequest.Create(URI);
//Set the login details
result.Credentials = GetCredentials();
//Do not keep alive (stateless mode)
result.KeepAlive = false;
result.UseBinary = true;
return result;
} /// <summary>
/// Get the credentials from username/password
/// </summary>
private System.Net.ICredentials GetCredentials()
{
return new System.Net.NetworkCredential(Username, Password);
} /// <summary>
/// returns a full path using CurrentDirectory for a relative file reference
/// </summary>
private string GetFullPath(string file)
{
if (file.Contains("/"))
{
return AdjustDir(file);
}
else
{
return this.CurrentDirectory + file;
}
} /// <summary>
/// Amend an FTP path so that it always starts with /
/// </summary>
/// <param name="path">Path to adjust</param>
/// <returns></returns>
/// <remarks></remarks>
private string AdjustDir(string path)
{
return ((path.StartsWith("/")) ? "" : "/").ToString() + path;
} private string GetDirectory(string directory)
{
string URI;
if (directory == "")
{
//build from current
URI = Hostname + this.CurrentDirectory;
_lastDirectory = this.CurrentDirectory;
}
else
{
if (!directory.StartsWith("/"))
{
throw (new ApplicationException("Directory should start with /"));
}
URI = this.Hostname + directory;
_lastDirectory = directory;
}
return URI;
} //stores last retrieved/set directory
private string _lastDirectory = ""; /// <summary>
/// Obtains a response stream as a string
/// </summary>
/// <param name="ftp">current FTP request</param>
/// <returns>String containing response</returns>
/// <remarks>FTP servers typically return strings with CR and
/// not CRLF. Use respons.Replace(vbCR, vbCRLF) to convert
/// to an MSDOS string</remarks>
private string GetStringResponse(FtpWebRequest ftp)
{
//Get the result, streaming to a string
string result = "";
using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse())
{
long size = response.ContentLength;
using (Stream datastream = response.GetResponseStream())
{
// 一中文亂碼問題 涂聚文 20180801
using (StreamReader sr = new StreamReader(datastream, System.Text.Encoding.GetEncoding("GB2312")))
{
_WelcomeMessage = response.WelcomeMessage;
_ExitMessage = response.ExitMessage;
result = sr.ReadToEnd();
sr.Close();
}
try
{
//Declare Event
NewMessageEventArgs e = new NewMessageEventArgs("RESPONSE", response.StatusDescription, response.StatusCode.ToString());
//Raise Event
OnNewMessageReceived(this, e);
}
catch
{ } datastream.Close();
}
response.Close();
}
return result;
} /// <summary>
/// Gets the size of an FTP request
/// </summary>
/// <param name="ftp"></param>
/// <returns></returns>
/// <remarks></remarks>
private long GetSize(FtpWebRequest ftp)
{
long size;
using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse())
{
size = response.ContentLength;
response.Close();
} return size;
}
#endregion #region "Properties"
private string _hostname;
/// <summary>
/// Hostname
/// </summary>
/// <value></value>
/// <remarks>Hostname can be in either the full URL format
/// ftp://ftp.myhost.com or just ftp.myhost.com
/// </remarks>
public string Hostname
{
get
{
if (_hostname.StartsWith("ftp://"))
{
return _hostname;
}
else
{
return "ftp://" + _hostname;
}
}
set
{
_hostname = value;
}
}
private string _username;
/// <summary>
/// Username property
/// </summary>
/// <value></value>
/// <remarks>Can be left blank, in which case 'anonymous' is returned</remarks>
public string Username
{
get
{
return (_username == "" ? "anonymous" : _username);
}
set
{
_username = value;
}
}
private string _password;
public string Password
{
get
{
return _password;
}
set
{
_password = value;
}
} /// <summary>
/// The CurrentDirectory value
/// </summary>
/// <remarks>Defaults to the root '/'</remarks>
private string _currentDirectory = "/";
public string CurrentDirectory
{
get
{
//return directory, ensure it ends with /
return _currentDirectory + ((_currentDirectory.EndsWith("/")) ? "" : "/").ToString();
}
set
{
if (!value.StartsWith("/"))
{
throw (new ApplicationException("Directory should start with /"));
}
_currentDirectory = value;
}
} #endregion #region Server Messages
string _WelcomeMessage, _ExitMessage;
public string WelcomeMessage
{
get
{
return _WelcomeMessage;
}
set
{
_WelcomeMessage = value;
}
}
public string ExitMessage
{
get
{
return _ExitMessage;
}
set
{
_ExitMessage = value;
}
}
#endregion }
#endregion #region "FTP file info class"
/// <summary>
/// Represents a file or directory entry from an FTP listing
/// </summary>
/// <remarks>
/// This class is used to parse the results from a detailed
/// directory list from FTP. It supports most formats of
/// </remarks>
public class FTPfileInfo
{ //Stores extended info about FTP file #region "Properties"
public string FullName
{
get
{
return Path + Filename;
}
}
public string Filename
{
get
{
return _filename;
}
}
public string Path
{
get
{
return _path;
}
}
public DirectoryEntryTypes FileType
{
get
{
return _fileType;
}
}
public long Size
{
get
{
return _size;
}
}
public DateTime FileDateTime
{
get
{
return _fileDateTime;
}
}
public string Permission
{
get
{
return _permission;
}
}
public string Extension
{
get
{
int i = this.Filename.LastIndexOf(".");
if (i >= 0 && i < (this.Filename.Length - 1))
{
return this.Filename.Substring(i + 1);
}
else
{
return "";
}
}
}
public string NameOnly
{
get
{
int i = this.Filename.LastIndexOf(".");
if (i > 0)
{
return this.Filename.Substring(0, i);
}
else
{
return this.Filename;
}
}
}
private string _filename;
private string _path;
private DirectoryEntryTypes _fileType;
private long _size;
private DateTime _fileDateTime;
private string _permission; #endregion /// <summary>
/// Identifies entry as either File or Directory
/// </summary>
public enum DirectoryEntryTypes
{
File,
Directory
} /// <summary>
/// Constructor taking a directory listing line and path
/// </summary>
/// <param name="line">The line returned from the detailed directory list</param>
/// <param name="path">Path of the directory</param>
/// <remarks></remarks>
public FTPfileInfo(string line, string path)
{
//parse line
Match m = GetMatchingRegex(line);
if (m == null)
{
//failed
throw (new ApplicationException("Unable to parse line: " + line));
}
else
{
_filename = m.Groups["name"].Value;
_path = path; Int64.TryParse(m.Groups["size"].Value, out _size);
//_size = System.Convert.ToInt32(m.Groups["size"].Value); _permission = m.Groups["permission"].Value;
string _dir = m.Groups["dir"].Value;
if (_dir != "" && _dir != "-")
{
_fileType = DirectoryEntryTypes.Directory;
}
else
{
_fileType = DirectoryEntryTypes.File;
} try
{
_fileDateTime = DateTime.Parse(m.Groups["timestamp"].Value);
}
catch (Exception)
{
_fileDateTime = Convert.ToDateTime(null);
} }
} private Match GetMatchingRegex(string line)
{
Regex rx;
Match m;
for (int i = 0; i <= _ParseFormats.Length - 1; i++)
{
rx = new Regex(_ParseFormats[i]);
m = rx.Match(line);
if (m.Success)
{
return m;
}
}
return null;
} #region "Regular expressions for parsing LIST results"
/// <summary>
/// List of REGEX formats for different FTP server listing formats
/// </summary>
/// <remarks>
/// The first three are various UNIX/LINUX formats, fourth is for MS FTP
/// in detailed mode and the last for MS FTP in 'DOS' mode.
/// I wish VB.NET had support for Const arrays like C# but there you go
/// </remarks>
private static string[] _ParseFormats = new string[] {
"(?<dir>[\\-d])(?<permission>([\\-r][\\-w][\\-xs]){3})\\s+\\d+\\s+\\w+\\s+\\w+\\s+(?<size>\\d+)\\s+(?<timestamp>\\w+\\s+\\d+\\s+\\d{4})\\s+(?<name>.+)",
"(?<dir>[\\-d])(?<permission>([\\-r][\\-w][\\-xs]){3})\\s+\\d+\\s+\\d+\\s+(?<size>\\d+)\\s+(?<timestamp>\\w+\\s+\\d+\\s+\\d{4})\\s+(?<name>.+)",
"(?<dir>[\\-d])(?<permission>([\\-r][\\-w][\\-xs]){3})\\s+\\d+\\s+\\d+\\s+(?<size>\\d+)\\s+(?<timestamp>\\w+\\s+\\d+\\s+\\d{1,2}:\\d{2})\\s+(?<name>.+)",
"(?<dir>[\\-d])(?<permission>([\\-r][\\-w][\\-xs]){3})\\s+\\d+\\s+\\w+\\s+\\w+\\s+(?<size>\\d+)\\s+(?<timestamp>\\w+\\s+\\d+\\s+\\d{1,2}:\\d{2})\\s+(?<name>.+)",
"(?<dir>[\\-d])(?<permission>([\\-r][\\-w][\\-xs]){3})(\\s+)(?<size>(\\d+))(\\s+)(?<ctbit>(\\w+\\s\\w+))(\\s+)(?<size2>(\\d+))\\s+(?<timestamp>\\w+\\s+\\d+\\s+\\d{2}:\\d{2})\\s+(?<name>.+)",
"(?<timestamp>\\d{2}\\-\\d{2}\\-\\d{2}\\s+\\d{2}:\\d{2}[Aa|Pp][mM])\\s+(?<dir>\\<\\w+\\>){0,1}(?<size>\\d+){0,1}\\s+(?<name>.+)" };
#endregion
}
#endregion #region "FTP Directory class"
/// <summary>
/// Stores a list of files and directories from an FTP result
/// </summary>
/// <remarks></remarks>
public class FTPdirectory : List<FTPfileInfo>
{ public FTPdirectory()
{
//creates a blank directory listing
} /// <summary>
/// Constructor: create list from a (detailed) directory string
/// </summary>
/// <param name="dir">directory listing string</param>
/// <param name="path"></param>
/// <remarks></remarks>
public FTPdirectory(string dir, string path)
{
foreach (string line in dir.Replace("\n", "").Split(System.Convert.ToChar('\r')))
{
//parse
if (line != "")
{
this.Add(new FTPfileInfo(line, path));
}
}
} /// <summary>
/// Filter out only files from directory listing
/// </summary>
/// <param name="ext">optional file extension filter</param>
/// <returns>FTPdirectory listing</returns>
public FTPdirectory GetFiles(string ext)
{
return this.GetFileOrDir(FTPfileInfo.DirectoryEntryTypes.File, ext);
} /// <summary>
/// Returns a list of only subdirectories
/// </summary>
/// <returns>FTPDirectory list</returns>
/// <remarks></remarks>
public FTPdirectory GetDirectories()
{
return this.GetFileOrDir(FTPfileInfo.DirectoryEntryTypes.Directory, "");
} //internal: share use function for GetDirectories/Files
private FTPdirectory GetFileOrDir(FTPfileInfo.DirectoryEntryTypes type, string ext)
{
FTPdirectory result = new FTPdirectory();
foreach (FTPfileInfo fi in this)
{
if (fi.FileType == type)
{
if (ext == "")
{
result.Add(fi);
}
else if (ext == fi.Extension)
{
result.Add(fi);
}
}
}
return result; } public bool FileExists(string filename)
{
foreach (FTPfileInfo ftpfile in this)
{
if (ftpfile.Filename == filename)
{
return true;
}
}
return false;
} private const char slash = '/'; public static string GetParentDirectory(string dir)
{
string tmp = dir.TrimEnd(slash);
int i = tmp.LastIndexOf(slash);
if (i > 0)
{
return tmp.Substring(0, i - 1);
}
else
{
throw (new ApplicationException("No parent for root"));
}
}
}
#endregion #region Events
public class DownloadProgressChangedArgs : EventArgs
{
//Private Members
private Int64 _BytesDownload;
private Int64 _TotalBytes; //Constructor
public DownloadProgressChangedArgs(Int64 BytesDownload, Int64 TotleBytes)
{
this._BytesDownload = BytesDownload;
this._TotalBytes = TotleBytes;
} //Public Members
public Int64 BytesDownloaded { get { return _BytesDownload; } }
public Int64 TotleBytes { get { return _TotalBytes; } }
} public class DownloadCompletedArgs : EventArgs
{
//Private Members
private bool _DownloadedCompleted;
private string _DownloadStatus; //Constructor
public DownloadCompletedArgs(string Status, bool Completed)
{
this._DownloadedCompleted = Completed;
this._DownloadStatus = Status;
} //Public Members
public String DownloadStatus { get { return _DownloadStatus; } }
public bool DownloadCompleted { get { return _DownloadedCompleted; } }
} public class NewMessageEventArgs : EventArgs
{
//Private Members
private string _Message;
private string _StatusCode;
private string _Type; //Constructor
public NewMessageEventArgs(string Type, string Status, string Code)
{
this._Message = Status;
this._StatusCode = Code;
this._Type = Type;
} //Public Members
public string StatusMessage { get { return _Message; } }
public string StatusCode { get { return _StatusCode; } }
public string StatusType { get { return _Type; } }
} public class UploadProgressChangedArgs : EventArgs
{
//Private Members
private Int64 _BytesUpload;
private Int64 _TotalBytes; //Constructor
public UploadProgressChangedArgs(Int64 BytesUpload, Int64 TotleBytes)
{
this._BytesUpload = BytesUpload;
this._TotalBytes = TotleBytes;
} //Public Members
public Int64 BytesUploaded { get { return _BytesUpload; } }
public Int64 TotleBytes { get { return _TotalBytes; } }
} public class UploadCompletedArgs : EventArgs
{
//Private Members
private bool _UploadCompleted;
private string _UploadStatus; //Constructor
public UploadCompletedArgs(string Status, bool Completed)
{
this._UploadCompleted = Completed;
this._UploadStatus = Status;
} //Public Members
public String UploadStatus { get { return _UploadStatus; } }
public bool UploadCompleted { get { return _UploadCompleted; } }
}
#endregion
}

  测试代码:

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.Net;
using FTPLibrary;
using System.Diagnostics;
using System.Reflection;
using System.IO; namespace ftpdemo
{ /// <summary>
/// 涂聚文 2017-08-01
/// </summary>
public partial class Form6 : Form
{
public FTPclient FtpClient;
ListViewItem Message;
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"]; //端口 /// <summary>
///
/// </summary>
/// <param name="byteCount"></param>
/// <returns></returns>
private string GetFileSize(double byteCount)
{
string size = "0 Bytes";
if (byteCount >= 1073741824.0)
size = String.Format("{0:##.##}", byteCount / 1073741824.0) + " GB";
else if (byteCount >= 1048576.0)
size = String.Format("{0:##.##}", byteCount / 1048576.0) + " MB";
else if (byteCount >= 1024.0)
size = String.Format("{0:##.##}", byteCount / 1024.0) + " KB";
else if (byteCount > 0 && byteCount < 1024.0)
size = byteCount.ToString() + " Bytes"; return size;
}
/// <summary>
/// Sets up the FTPClient for this Form. Called from frmLogin.
/// </summary>
/// <param name="client">FTPclient on frmLogin is used to refrence the FtpClient here.</param>
public void SetFtpClient(FTPclient client)
{
//Set FtpClient
FtpClient = client; //Display the Welcome Message
Message = new ListViewItem();
Message.Text = DateTime.Now.ToLongTimeString() + " " + DateTime.Now.ToLongDateString();
Message.SubItems.Add("Welcome Message");
Message.SubItems.Add(FtpClient.WelcomeMessage);
Message.SubItems.Add("No Code");
Message.SubItems.Add("/");
lstMessages.Items.Add(Message); //Setup OnMessageReceived Event
FtpClient.OnNewMessageReceived += new FTPclient.NewMessageHandler(FtpClient_OnNewMessageReceived); //Open and Display Root Directory and Files/Folders in it
foreach (FTPfileInfo folder in FtpClient.ListDirectoryDetail("/"))
{
ListViewItem item = new ListViewItem();
item.Text = folder.Filename;
if (folder.FileType == FTPfileInfo.DirectoryEntryTypes.Directory)
item.SubItems.Add("Folder");
else
item.SubItems.Add("File"); item.SubItems.Add(folder.FullName);
item.SubItems.Add(folder.Permission);
item.SubItems.Add(folder.FileDateTime.ToShortTimeString() + folder.FileDateTime.ToShortDateString());
item.SubItems.Add(GetFileSize(folder.Size));
lstRemoteSiteFiles.Items.Add(item);
}
}
/// <summary>
///
/// </summary>
/// <param name="myObject"></param>
/// <param name="e"></param>
private void FtpClient_OnNewMessageReceived(object myObject, NewMessageEventArgs e)
{
//Display Meesage in lstMessages
Message = new ListViewItem();
Message.Text = DateTime.Now.ToLongTimeString() + " " + DateTime.Now.ToLongDateString();
Message.SubItems.Add(e.StatusType);
Message.SubItems.Add(e.StatusMessage);
Message.SubItems.Add(e.StatusCode);
Message.SubItems.Add(txtRemoteDirectory.Text);
lstMessages.Items.Add(Message); this.lstMessages.EnsureVisible(this.lstMessages.Items.Count - 1);
}
/// <summary>
/// Reload all Directories and Files in Current Directory
/// </summary>
private void RefreshDirectory()
{
//Clear all items
lstRemoteSiteFiles.Items.Clear(); //Open and Display Root Directory
foreach (FTPfileInfo folder in FtpClient.ListDirectoryDetail(txtRemoteDirectory.Text))
{
ListViewItem item = new ListViewItem();
item.Text = folder.Filename;
if (folder.FileType == FTPfileInfo.DirectoryEntryTypes.Directory)
item.SubItems.Add("Folder");
else
item.SubItems.Add("File"); item.SubItems.Add(folder.FullName);
item.SubItems.Add(folder.Permission);
item.SubItems.Add(folder.FileDateTime.ToShortTimeString() + folder.FileDateTime.ToShortDateString());
item.SubItems.Add(folder.Size.ToString());
lstRemoteSiteFiles.Items.Add(item);
}
}
/// <summary>
///
/// </summary>
public Form6()
{
InitializeComponent(); //Set Selected Directory
txtRemoteDirectory.Text = "/";
lstRemoteSiteFiles.FullRowSelect = true;
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form6_Load(object sender, EventArgs e)
{
//Set FTP
FTPclient objFtp = new FTPclient(ftpServer, user,pwd);
objFtp.CurrentDirectory = "/";
SetFtpClient(objFtp); }
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void lstRemoteSiteFiles_SelectedIndexChanged(object sender, EventArgs e)
{ }
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void lstRemoteSiteFiles_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (lstRemoteSiteFiles.Items.Count != 0)
{
try
{
if (lstRemoteSiteFiles.SelectedItems[0].SubItems[1].Text == "File")
{
//Enable the buttons that are related to the FILE
// btnRename.Enabled = true;
// btnDownload.Enabled = true;
//Set Current Directory for Download
FtpClient.CurrentDirectory = txtRemoteDirectory.Text;
//Its a File, so Ask them if they want to Save it...
if (MessageBox.Show("Do you want to save this file: " + txtRemoteDirectory.Text + lstRemoteSiteFiles.SelectedItems[0].Text + "/" + "?", "Download File?", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.Yes)
{
//Save the File to location
//downloadToolStripMenuItem_Click(this, e);
}
}
else if (lstRemoteSiteFiles.SelectedItems[0].SubItems[1].Text == "Folder") // Its a Directory
{
//Set Directory to txtRemoteDirectory.Text + selectedItem + "/"
//Result - /SelectedDirecotory/ -- good for navigation, keeping user informed and code :)
txtRemoteDirectory.Text += lstRemoteSiteFiles.SelectedItems[0].Text + "/";
lstRemoteSiteFiles.Items.Clear(); //Set Current Dir
FtpClient.CurrentDirectory = txtRemoteDirectory.Text; //Get Files and Folders from Selected Direcotry
foreach (FTPfileInfo folder in FtpClient.ListDirectoryDetail(txtRemoteDirectory.Text))
{
ListViewItem item = new ListViewItem();
item.Text = folder.Filename;
if (folder.FileType == FTPfileInfo.DirectoryEntryTypes.Directory)
item.SubItems.Add("Folder");
else
item.SubItems.Add("File"); item.SubItems.Add(folder.FullName);
item.SubItems.Add(folder.Permission);
item.SubItems.Add(folder.FileDateTime.ToShortDateString()+" "+folder.FileDateTime.ToShortTimeString());
item.SubItems.Add(GetFileSize(folder.Size));
lstRemoteSiteFiles.Items.Add(item);
}
}
}
catch { }
}
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void lstRemoteSiteFiles_ItemDrag(object sender, ItemDragEventArgs e)
{ }
}
}

  

csharp: FTP Client Library using System.Net.FtpWebRequest的更多相关文章

  1. 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 ...

  2. csharp:FTP Client Library using FtpWebRequest or Sockets

    https://netftp.codeplex.com/SourceControl/latest http://ftplib.codeplex.com/ https://www.codeproject ...

  3. C# Ftp Client 基本操作

    C# Ftp Client 上传.下载与删除 简单介绍一下Ftp Client 上传.下载与删除,这是目前比较常用的命令,各个方法其实都差不多,重点是了解Ftp命令协议. 1.建立连接 public ...

  4. Memcached通用类(基于Memcached Client Library)

    分享下自己编写的Memcached通用类.欢迎大家帮忙指点下哈~ 使用的是.NET memcached client library 客户端+Memcached Providers using Sys ...

  5. 分布式缓存系统Memcached简介与实践(.NET memcached client library)

    缘起: 在数据驱动的web开发中,经常要重复从数据库中取出相同的数据,这种重复极大的增加了数据库负载.缓存是解决这个问题的好办法.但是ASP.NET中的虽然已经可以实现对页面局部进行缓存,但还是不够灵 ...

  6. Intro to Jedis – the Java Redis Client Library

    转自:http://www.baeldung.com/jedis-java-redis-client-library 1. Overview This article is an introducti ...

  7. System.Net.FtpWebRequest.cs

    ylbtech-System.Net.FtpWebRequest.cs 实现文件传输协议(FTP)客户端. 1.返回顶部 1. #region 程序集 System, Version=4.0.0.0, ...

  8. Ubuntu Filezilla FTP Client 安装

    /************************************************************************************* * Ubuntu File ...

  9. 谷歌正式发布Google APIs Client Library for .NET

    好消息,特大好消息! 英文原文:Google API library for .NET paves the way for Google services on Windows phone 本月 17 ...

随机推荐

  1. We FALL ASleep At Night, We Do REST Right

    We Do Sleep At Night, We Do REST Right 前言 REST 起源 REST 约束 客户端 - 服务端 无状态 缓存 统一接口 分层系统 按需代码 统一接口约束 资源识 ...

  2. 9.indicate、xutils、json

    json数据  页签详情页数据   public class TabData { public int retcode; public TabDetail data;//不是数组的话类型就是这个 pu ...

  3. jQuery的JS库在本地运行项目时提示无法加载

    最近公司有个项目在我本地运行时引用本地的jquery.js,浏览器提示无法加载 <script src="/js/newperson/jquery-1.11.3.min.js" ...

  4. PCIE 2.0协议概念基本科普

    PCIE的概念:是电脑总线PCI的一种,它沿用现有的PCI编程概念及通信标准,但建基于更快的串行通信系统. 英特尔是该接口的主要支持者.PCIe仅应用于内部互连.由于PCIe是基于现有的PCI系统,只 ...

  5. win10 插入16k采样的耳机无法播放和录音的问题定位

    平时做智能耳机,需要经常在windows上测试不同采样率的声音信号.可是,最近在16k双声道输入的情况下, 无论系统都使用该耳机进行播放,该问题思索了好久,一直没有解决办法. 今天无意中使用了wind ...

  6. python zip压缩文件 并移动到指定目录

    需要引入的3个包: import os import shutil import zipfile 1. # 创建zip文件对象your_zip_file_obj = zipfile.ZipFile(' ...

  7. java中的字符、字符串及数字之间的转换(转)

    一.string 和int之间的转换 1.string转换成int  :Integer.valueOf("12") 2.int转换成string : String.valueOf( ...

  8. Windows下为 Eclipse 配置 C/C++ 编译环境(转)

    1.Eclipse及CDT的安装 CDT的全称是C/C++ DevelopmentTools,CDT使得Eclipse能够支持C/C++的开发.直接下载 eclipse CDT 集成版 下载地址:ht ...

  9. swaggerui集成oauth implicit

    swaggerui集成oauth implicit 添加引用 Swashbuckle.AspNetCore IdentityServer4.AccessTokenValidation 预先准备好Ide ...

  10. mongodb数据库添加权限及简单数据库命令操作笔记

    加固mongodb建议:修改数据库默认端口,添加数据库访问权限: 启动数据库(裸奔):C:\mongodb\bin>mongod --dbpath C:\MongoDB\data(同时用--db ...