575 lines
17 KiB
C#
575 lines
17 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Text;
|
|
|
|
|
|
namespace AR.FTPClient
|
|
{
|
|
public partial class FTPClient : IFTPClient
|
|
{
|
|
public string errorMessage { get; set; }
|
|
|
|
private int bufferSize = 2048;
|
|
private int timeout = 20000;
|
|
|
|
#region "Contstruct"
|
|
|
|
public FTPClient() : this("127.0.0.1", "Anonymous", "") { }
|
|
|
|
public FTPClient(string Host, string UserID, string UserPass) :
|
|
this(Host, UserID, UserPass, 21)
|
|
{ }
|
|
|
|
public FTPClient(string Host, string UserID, string UserPass, bool passive) :
|
|
this(Host, UserID, UserPass, 21, passive)
|
|
{ }
|
|
|
|
public FTPClient(string Host, string UserID, string UserPass, int port) :
|
|
this(Host, UserID, UserPass, port, false)
|
|
{ }
|
|
|
|
public FTPClient(string host, string userid, string userpass, int port, bool passive)
|
|
{
|
|
Host = host;
|
|
UserID = userid;
|
|
UserPassword = userpass;
|
|
Port = port;
|
|
PassiveMode = passive;
|
|
this.TextEncoding = System.Text.Encoding.UTF8;
|
|
}
|
|
#endregion
|
|
|
|
public event EventHandler<MessageEventArgs> Message;
|
|
public event EventHandler<ListProgressEventArgs> ListPrgress;
|
|
|
|
#region "Properties"
|
|
|
|
/// <summary>
|
|
/// 접속하려는 FTP서버의 IP혹은 도메인 주소를 입력하세요
|
|
/// 기본값 : 127.0.0.1
|
|
/// </summary>
|
|
public string Host { get; set; }
|
|
/// <summary>
|
|
/// FTP의 사용자 ID
|
|
/// 기본값 : Anonymous
|
|
/// </summary>
|
|
public string UserID { get; set; }
|
|
/// <summary>
|
|
/// FTP 사용자 ID의 암호
|
|
/// 기본값 : 없음
|
|
/// </summary>
|
|
public string UserPassword { get; set; }
|
|
/// <summary>
|
|
/// FTP 접속 포트
|
|
/// 기본값 : 21
|
|
/// </summary>
|
|
public int Port { get; set; }
|
|
/// <summary>
|
|
/// FTP 접속 방식 (능동형/수동형)
|
|
/// </summary>
|
|
public bool PassiveMode { get; set; }
|
|
|
|
/// <summary>
|
|
/// 문자수신시 사용할 인코딩 방식
|
|
/// </summary>
|
|
public System.Text.Encoding TextEncoding { get; set; }
|
|
|
|
#endregion
|
|
public void Dispose()
|
|
{
|
|
|
|
}
|
|
/// <summary>
|
|
/// 파일을 다운로드 합니다.
|
|
/// </summary>
|
|
/// <param name="remoteFile">원격위치의 전체 경로</param>
|
|
/// <param name="localFile">로컬위치의 전체 경로</param>
|
|
public Boolean Download(string remoteFile, string localFile, bool overwrite = false)
|
|
{
|
|
FtpWebRequest ftpRequest = null;
|
|
FtpWebResponse ftpResponse = null;
|
|
Stream ftpStream = null;
|
|
|
|
//overwrite funcion - 190622 - chi
|
|
errorMessage = string.Empty;
|
|
if (overwrite == false && System.IO.File.Exists(localFile))
|
|
{
|
|
errorMessage = "Target file alreay exists";
|
|
return false;
|
|
}
|
|
else if (overwrite == true && System.IO.File.Exists(localFile))
|
|
{
|
|
try
|
|
{
|
|
System.IO.File.Delete(localFile);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = ex.Message;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool retval = true;
|
|
try
|
|
{
|
|
long Receive = 0;
|
|
var url = CombineUrl(remoteFile);
|
|
|
|
ftpRequest = (FtpWebRequest)FtpWebRequest.Create(url);
|
|
ftpRequest.Credentials = new NetworkCredential(this.UserID, this.UserPassword);
|
|
ftpRequest.UseBinary = true;
|
|
ftpRequest.UsePassive = this.PassiveMode;
|
|
ftpRequest.KeepAlive = true;
|
|
ftpRequest.ReadWriteTimeout = this.timeout;
|
|
ftpRequest.Method = WebRequestMethods.Ftp.DownloadFile;
|
|
ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
|
|
ftpStream = ftpResponse.GetResponseStream();
|
|
FileStream localFileStream = new FileStream(localFile, FileMode.Create);
|
|
byte[] byteBuffer = new byte[bufferSize];
|
|
int bytesRead = ftpStream.Read(byteBuffer, 0, bufferSize);
|
|
Receive += bytesRead;
|
|
if (ListPrgress != null)
|
|
ListPrgress(this, new ListProgressEventArgs(Receive));
|
|
try
|
|
{
|
|
while (bytesRead > 0)
|
|
{
|
|
localFileStream.Write(byteBuffer, 0, bytesRead);
|
|
bytesRead = ftpStream.Read(byteBuffer, 0, bufferSize);
|
|
Receive += bytesRead;
|
|
if (ListPrgress != null)
|
|
ListPrgress(this, new ListProgressEventArgs(Receive));
|
|
}
|
|
}
|
|
catch (Exception ex) { retval = false; Console.WriteLine(ex.ToString()); }
|
|
localFileStream.Close();
|
|
ftpStream.Close();
|
|
ftpResponse.Close();
|
|
ftpRequest = null;
|
|
}
|
|
catch (Exception ex) { retval = false; this.errorMessage = ex.Message; Console.WriteLine(ex.ToString()); }
|
|
return retval;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 파일을 업로드 합니다.
|
|
/// </summary>
|
|
/// <param name="remoteFile">원격위치의 전체 경로</param>
|
|
/// <param name="localFile">로컬위치의 전체 경로</param>
|
|
/// <returns></returns>
|
|
public Boolean Upload(string remoteFile, string localFile)
|
|
{
|
|
FtpWebRequest ftpRequest = null;
|
|
FtpWebResponse ftpResponse = null;
|
|
Stream ftpStream = null;
|
|
try
|
|
{
|
|
var url = CombineUrl(remoteFile);
|
|
ftpRequest = (FtpWebRequest)FtpWebRequest.Create(url);
|
|
ftpRequest.Credentials = new NetworkCredential(UserID, UserPassword);
|
|
ftpRequest.UseBinary = true;
|
|
ftpRequest.UsePassive = PassiveMode;
|
|
ftpRequest.KeepAlive = true;
|
|
ftpRequest.ReadWriteTimeout = this.timeout;
|
|
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
|
|
ftpStream = ftpRequest.GetRequestStream();
|
|
FileStream localFileStream = new FileStream(localFile, FileMode.Open);
|
|
byte[] byteBuffer = new byte[bufferSize];
|
|
int bytesSent = localFileStream.Read(byteBuffer, 0, bufferSize);
|
|
Boolean bError = false;
|
|
try
|
|
{
|
|
System.Diagnostics.Stopwatch wat = new System.Diagnostics.Stopwatch();
|
|
wat.Restart();
|
|
while (bytesSent != 0)
|
|
{
|
|
ftpStream.Write(byteBuffer, 0, bytesSent);
|
|
bytesSent = localFileStream.Read(byteBuffer, 0, bufferSize);
|
|
}
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
bError = true;
|
|
}
|
|
localFileStream.Close();
|
|
ftpStream.Close();
|
|
ftpRequest = null;
|
|
if (bError) return false;
|
|
else return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
this.errorMessage = ex.Message;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 원격파일을 삭제 합니다.
|
|
/// </summary>
|
|
/// <param name="remotefile"></param>
|
|
public Boolean Delete(string remotefile)
|
|
{
|
|
FtpWebRequest ftpRequest = null;
|
|
FtpWebResponse ftpResponse = null;
|
|
Stream ftpStream = null;
|
|
try
|
|
{
|
|
var url = CombineUrl(remotefile);
|
|
ftpRequest = (FtpWebRequest)WebRequest.Create(url);
|
|
ftpRequest.Credentials = new NetworkCredential(UserID, UserPassword);
|
|
ftpRequest.UseBinary = true;
|
|
ftpRequest.UsePassive = this.PassiveMode;
|
|
ftpRequest.KeepAlive = true;
|
|
ftpRequest.ReadWriteTimeout = this.timeout;
|
|
ftpRequest.Method = WebRequestMethods.Ftp.DeleteFile;
|
|
ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
|
|
ftpResponse.Close();
|
|
ftpRequest = null;
|
|
return true;
|
|
}
|
|
catch (Exception ex) { this.errorMessage = ex.Message; return false; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 원격파일의 이름을 변경 합니다.
|
|
/// </summary>
|
|
/// <param name="currentFileNameAndPath"></param>
|
|
/// <param name="newFileName"></param>
|
|
public Boolean rename(string currentFileNameAndPath, string newFileName)
|
|
{
|
|
FtpWebRequest ftpRequest = null;
|
|
FtpWebResponse ftpResponse = null;
|
|
Stream ftpStream = null;
|
|
try
|
|
{
|
|
var url = CombineUrl(currentFileNameAndPath);
|
|
ftpRequest = (FtpWebRequest)WebRequest.Create(url);
|
|
ftpRequest.Credentials = new NetworkCredential(UserID, UserPassword);
|
|
ftpRequest.UsePassive = this.PassiveMode;
|
|
ftpRequest.ReadWriteTimeout = this.timeout;
|
|
ftpRequest.UseBinary = true;
|
|
ftpRequest.KeepAlive = true;
|
|
ftpRequest.Method = WebRequestMethods.Ftp.Rename;
|
|
ftpRequest.RenameTo = newFileName;
|
|
ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
|
|
ftpResponse.Close();
|
|
ftpRequest = null;
|
|
return true;
|
|
}
|
|
catch (Exception ex) { this.errorMessage = ex.Message; return false; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 원격위치에 폴더를 생성 합니다.
|
|
/// 트리구조로 폴더를 생성하지 않습니다. 여러개의 폴더를 생성하려면 각각 호출 해야 합니다.
|
|
/// </summary>
|
|
/// <param name="newDirectory"></param>
|
|
/// <returns></returns>
|
|
public bool createDirectory(string newDirectory)
|
|
{
|
|
FtpWebRequest ftpRequest = null;
|
|
FtpWebResponse ftpResponse = null;
|
|
Stream ftpStream = null;
|
|
try
|
|
{
|
|
var url = CombineUrl(newDirectory, false);
|
|
ftpRequest = (FtpWebRequest)WebRequest.Create(url);
|
|
ftpRequest.Credentials = new NetworkCredential(UserID, UserPassword);
|
|
ftpRequest.UsePassive = this.PassiveMode;
|
|
ftpRequest.UseBinary = true;
|
|
ftpRequest.KeepAlive = true;
|
|
ftpRequest.ReadWriteTimeout = this.timeout;
|
|
ftpRequest.Method = WebRequestMethods.Ftp.MakeDirectory;
|
|
ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
|
|
ftpResponse.Close();
|
|
ftpRequest = null;
|
|
return true;
|
|
}
|
|
catch (Exception ex) { this.errorMessage = ex.Message; return false; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 원격위치의 폴더를 삭제합니다. 폴더 삭제 전 대상 폴더는 비어있어야 합니다.
|
|
/// </summary>
|
|
/// <param name="Directory"></param>
|
|
/// <returns></returns>
|
|
public bool RemoveDirectory(string Directory)
|
|
{
|
|
FtpWebRequest ftpRequest = null;
|
|
FtpWebResponse ftpResponse = null;
|
|
Stream ftpStream = null;
|
|
try
|
|
{
|
|
var url = CombineUrl(Directory, false);
|
|
ftpRequest = (FtpWebRequest)WebRequest.Create(url);
|
|
ftpRequest.Credentials = new NetworkCredential(UserID, UserPassword);
|
|
ftpRequest.UsePassive = this.PassiveMode;
|
|
ftpRequest.UseBinary = true;
|
|
ftpRequest.KeepAlive = true;
|
|
ftpRequest.ReadWriteTimeout = this.timeout;
|
|
ftpRequest.Method = WebRequestMethods.Ftp.RemoveDirectory;
|
|
ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
|
|
ftpResponse.Close();
|
|
ftpRequest = null;
|
|
return true;
|
|
}
|
|
catch (Exception ex) { this.errorMessage = ex.Message; return false; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 파일의 생성일자 반환
|
|
/// </summary>
|
|
/// <param name="fileName"></param>
|
|
/// <returns></returns>
|
|
public string getFileCreatedDateTime(string fileName)
|
|
{
|
|
FtpWebRequest ftpRequest = null;
|
|
FtpWebResponse ftpResponse = null;
|
|
Stream ftpStream = null;
|
|
try
|
|
{
|
|
var url = CombineUrl(fileName);
|
|
ftpRequest = (FtpWebRequest)WebRequest.Create(url);
|
|
ftpRequest.Credentials = new NetworkCredential(UserID, UserPassword);
|
|
ftpRequest.UsePassive = this.PassiveMode;
|
|
ftpRequest.UseBinary = true;
|
|
ftpRequest.KeepAlive = true;
|
|
ftpRequest.ReadWriteTimeout = this.timeout;
|
|
ftpRequest.Method = WebRequestMethods.Ftp.GetDateTimestamp;
|
|
ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
|
|
ftpStream = ftpResponse.GetResponseStream();
|
|
StreamReader ftpReader = new StreamReader(ftpStream, this.TextEncoding);
|
|
string fileInfo = null;
|
|
try { fileInfo = ftpReader.ReadToEnd(); }
|
|
catch (Exception ex) { Console.WriteLine(ex.ToString()); }
|
|
ftpReader.Close();
|
|
ftpStream.Close();
|
|
ftpResponse.Close();
|
|
ftpRequest = null;
|
|
return fileInfo;
|
|
}
|
|
catch (Exception ex) { this.errorMessage = ex.Message; Console.WriteLine(ex.ToString()); }
|
|
return "";
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 파일의 크기를 반환
|
|
/// </summary>
|
|
/// <param name="fileName"></param>
|
|
/// <returns></returns>
|
|
public string getFileSize(string fileName)
|
|
{
|
|
FtpWebRequest ftpRequest = null;
|
|
FtpWebResponse ftpResponse = null;
|
|
Stream ftpStream = null;
|
|
try
|
|
{
|
|
var url = CombineUrl(fileName);
|
|
ftpRequest = (FtpWebRequest)WebRequest.Create(url);
|
|
ftpRequest.Credentials = new NetworkCredential(UserID, UserPassword);
|
|
ftpRequest.UseBinary = true;
|
|
ftpRequest.UsePassive = this.PassiveMode;
|
|
ftpRequest.KeepAlive = true;
|
|
ftpRequest.ReadWriteTimeout = this.timeout;
|
|
ftpRequest.Method = WebRequestMethods.Ftp.GetFileSize;
|
|
ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
|
|
ftpStream = ftpResponse.GetResponseStream();
|
|
StreamReader ftpReader = new StreamReader(ftpStream, this.TextEncoding);
|
|
string fileInfo = null;
|
|
try { while (ftpReader.Peek() != -1) { fileInfo = ftpReader.ReadToEnd(); } }
|
|
catch (Exception ex) { Console.WriteLine(ex.ToString()); }
|
|
ftpReader.Close();
|
|
ftpStream.Close();
|
|
ftpResponse.Close();
|
|
ftpRequest = null;
|
|
return fileInfo;
|
|
}
|
|
catch (Exception ex) { errorMessage = ex.Message; Console.WriteLine(ex.ToString()); }
|
|
return "";
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 폴더와 파일의 이름만 반환 합니다.
|
|
/// </summary>
|
|
/// <param name="directory"></param>
|
|
/// <returns></returns>
|
|
public string[] directoryListSimple(string directory)
|
|
{
|
|
FtpWebRequest ftpRequest = null;
|
|
FtpWebResponse ftpResponse = null;
|
|
Stream ftpStream = null;
|
|
errorMessage = string.Empty;
|
|
try
|
|
{
|
|
var url = CombineUrl(directory, false);
|
|
if (url.EndsWith("/") == false) url += "/";
|
|
ftpRequest = (FtpWebRequest)WebRequest.Create(url);
|
|
ftpRequest.Credentials = new NetworkCredential(UserID, UserPassword);
|
|
ftpRequest.UseBinary = true;
|
|
ftpRequest.UsePassive = PassiveMode;
|
|
ftpRequest.KeepAlive = true;
|
|
ftpRequest.ReadWriteTimeout = this.timeout;
|
|
ftpRequest.ReadWriteTimeout = 30000;
|
|
ftpRequest.Timeout = 30000;
|
|
ftpRequest.Method = WebRequestMethods.Ftp.ListDirectory;
|
|
|
|
ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
|
|
ftpStream = ftpResponse.GetResponseStream();
|
|
StreamReader ftpReader = new StreamReader(ftpStream, this.TextEncoding);
|
|
string directoryRaw = null;
|
|
try
|
|
{
|
|
while (ftpReader.Peek() != -1)
|
|
{
|
|
var dataLIne = ftpReader.ReadLine();
|
|
if (dataLIne.Trim() != "")
|
|
{
|
|
if (directoryRaw != null && directoryRaw != "") directoryRaw += "|";
|
|
directoryRaw += dataLIne;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex) { errorMessage += "\n" + ex.Message; }
|
|
ftpReader.Close();
|
|
ftpStream.Close();
|
|
ftpResponse.Close();
|
|
ftpRequest = null;
|
|
try { string[] directoryList = directoryRaw.Split("|".ToCharArray()); return directoryList; }
|
|
catch (Exception ex) { errorMessage += "\n" + ex.Message; }
|
|
}
|
|
catch (Exception ex) { errorMessage = ex.Message; Console.WriteLine(ex.ToString()); }
|
|
return new string[] { "" };
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 폴더 및 파일의 정보를 상세하게 표시합니다.
|
|
/// </summary>
|
|
/// <param name="directory"></param>
|
|
/// <returns></returns>
|
|
public FTPdirectory ListDirectoryDetail(string directory)
|
|
{
|
|
FtpWebRequest ftpRequest = null;
|
|
FtpWebResponse ftpResponse = null;
|
|
Stream ftpStream = null;
|
|
errorMessage = string.Empty;
|
|
try
|
|
{
|
|
var url = CombineUrl(directory, false);
|
|
|
|
if (url.EndsWith("/") == false) url += "/";
|
|
ftpRequest = (FtpWebRequest)WebRequest.Create(url);
|
|
ftpRequest.Credentials = new NetworkCredential(UserID, UserPassword);
|
|
ftpRequest.UsePassive = true;
|
|
ftpRequest.UseBinary = true;
|
|
ftpRequest.KeepAlive = false;
|
|
ftpRequest.ReadWriteTimeout = this.timeout;
|
|
ftpRequest.ReadWriteTimeout = 30000;
|
|
ftpRequest.Timeout = 30000;
|
|
ftpRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
|
|
ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
|
|
ftpStream = ftpResponse.GetResponseStream();
|
|
|
|
StreamReader ftpReader = new StreamReader(ftpStream, this.TextEncoding);
|
|
string directoryRaw = null;
|
|
|
|
try { while (ftpReader.Peek() != -1) { directoryRaw += ftpReader.ReadLine() + "\r"; } }
|
|
catch (Exception ex) { errorMessage += "\n" + ex.Message; }
|
|
ftpReader.Close();
|
|
ftpStream.Close();
|
|
ftpResponse.Close();
|
|
ftpRequest = null;
|
|
directoryRaw = directoryRaw.Replace("\r\n", "\r").TrimEnd((char)0x0D);
|
|
return new FTPdirectory(directoryRaw, directory);
|
|
}
|
|
catch (Exception ex) { errorMessage += "\n" + ex.Message; }
|
|
return null;
|
|
}
|
|
|
|
#region "utillity"
|
|
|
|
/// <summary>
|
|
/// Url을 Host와 결합하여 생성
|
|
/// </summary>
|
|
/// <param name="file">경로명</param>
|
|
/// <param name="isfile">파일인지 여부</param>
|
|
/// <returns></returns>
|
|
string CombineUrl(string file, bool isfile = true)
|
|
{
|
|
file = file.Replace("\\", "/");
|
|
string url = this.Host;
|
|
if (this.Host.ToLower().StartsWith("ftp://") == false) url = "ftp://" + url;
|
|
if (url.Substring(5).LastIndexOf(':') == -1)
|
|
url += ":" + this.Port.ToString();
|
|
|
|
if (this.Host.EndsWith("/")) url = this.Host.Substring(0, Host.Length - 1);
|
|
|
|
if (file.StartsWith("/"))
|
|
url = url + System.Web.HttpUtility.UrlPathEncode(file);
|
|
else
|
|
url = url + "/" + System.Web.HttpUtility.UrlPathEncode(file);
|
|
|
|
url = url.Replace("#", "%23");
|
|
|
|
if (isfile)
|
|
return url;
|
|
else
|
|
return url + "/";
|
|
}
|
|
public string PathCombine(string path, string add)
|
|
{
|
|
var newpath = string.Empty;
|
|
if (path.EndsWith("/")) newpath = path + add;
|
|
else newpath = path + "/" + add;
|
|
if (!newpath.EndsWith("/")) newpath += '/';
|
|
return newpath;
|
|
|
|
}
|
|
public string PathFileCombine(string path, string add)
|
|
{
|
|
var newpath = string.Empty;
|
|
if (path.EndsWith("/")) newpath = path + add;
|
|
else newpath = path + "/" + add;
|
|
if (newpath.EndsWith("/")) newpath = newpath.Substring(0, newpath.Length - 1);
|
|
return newpath;
|
|
|
|
}
|
|
public string getParent(string path)
|
|
{
|
|
if (path == "/") return path;
|
|
else if (path == "") return "/";
|
|
else
|
|
{
|
|
//서브폴더를 찾아서 처리해준다.
|
|
if (path.IndexOf('/') == -1) return "/";
|
|
else
|
|
{
|
|
if (path.EndsWith("/")) path = path.Substring(0, path.Length - 1);
|
|
var slashindex = path.LastIndexOf('/');
|
|
var parent = path.Substring(0, slashindex);
|
|
if (!parent.EndsWith("/")) parent += '/';
|
|
return parent;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void RaiseMessage(Boolean isError, string message)
|
|
{
|
|
if (isError) errorMessage = message; //170920
|
|
if (Message != null) Message(this, new MessageEventArgs(isError, message));
|
|
}
|
|
#endregion
|
|
}
|
|
}
|