using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;

using Cosmos.BaseFrame;
using Cosmos.UserFrame;

namespace Cosmos.Common
{
    /// <summary>
    /// FTP를 위한 유틸 클래스입니다.
    /// </summary>
    public class FTP
    {
        #region 멤버 변수 & 프로퍼티
        /// <summary>
        /// 
        /// </summary>
        private string host;

        /// <summary>
        /// FTP 서버 호스트명(IP)를 가져옵니다.
        /// </summary>
        public string Host
        {
            get { return host; }
            private set { host = value; }
        }

        private string userName;

        /// <summary>
        /// 사용자 명을 가져옵니다.
        /// </summary>
        public string UserName
        {
            get { return userName; }
            private set { userName = value; }
        }

        private string password;
        /// <summary>
        /// 비밀번호를 가져옵니다.
        /// </summary>
        public string Password
        {
            get { return password; }
            private set { password = value; }
        }

        /// <summary>
        /// FTP 델리게이트
        /// </summary>
        /// <param name="sFileName"></param>
        /// <param name="nDownSize"></param>
        /// <param name="nTotalSize"></param>
        public delegate void DelegateFTP(string sFileName, long nDownSize, long nTotalSize);

        /// <summary>
        /// 델리게이트 선언 변수
        /// </summary>
        public static DelegateFTP m_delegateFTP = null;

        
        /// <summary>
        /// StateServer Object (StateServer 객체)
        /// </summary>
        public StateServer StateObject = (StateServer)StateServer.GetInstance();//2017.12.05;미주 구분을 위해 추가; girak.kim

        /// <summary>
        /// POS Status Value (POS 상태값)
        /// </summary>
        private PosStatus m_cPosStatus = null;//2017.12.05;미주 구분을 위해 추가; girak.kim

        #endregion

        #region 생성자
        /// <summary>
        /// FXFtpUtil의 새 인스턴스를 생성합니다.
        /// </summary>
        /// <param name="host">FTP 서버 주소 입니다.</param>
        /// <param name="userName">FTP 사용자 아이디 입니다.</param>
        /// <param name="password">FTP 비밀번호 입니다.</param>
        public FTP(string host, string userName, string password)
        {
            this.Host = host;
            this.UserName = userName;
            this.Password = password;

            m_cPosStatus = (PosStatus)StateObject.POS;//2017.12.05;미주 구분을 위해 추가; girak.kim
        }
        #endregion

        #region 델리게이트 이벤트 핸들 설정
        /// <summary>
        /// 델리게이트 이벤트 핸들 설정
        /// </summary>
        /// <param name="delegateOPOS"></param>
        public static void SetEventHandle(DelegateFTP delegateFTP)
        {
            try
            {
                m_delegateFTP = delegateFTP;
            }
            catch (Exception ex)
            {
                UserLog.WriteLogFile(UserCom.LOG_ERROR, System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,
                                    "FTP.SetEventHandle()", "Exception." + ex.Message);
            }
        }

        /// <summary>
        /// 델리게이트 이벤트 핸들 해제
        /// </summary>
        public static void ReleaseEventHandle()
        {
            try
            {
                m_delegateFTP = null;
            }
            catch (Exception ex)
            {
                UserLog.WriteLogFile(UserCom.LOG_ERROR, System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,
                                    "FTP.ReleaseEventHandle()", "Exception." + ex.Message);
            }
        }
        #endregion 

        #region 메서드

        /// <summary>
        /// FTP 서버의 파일을 Delete 합니다.
        /// </summary>
        /// <param name="ftpFilePath">파일을 Delete 할 FTP 전체 경로 입니다.</param>
        /// <returns></returns>
        #region public bool DeleteFile(string ftpFilePath)
        public bool DeleteFile(string ftpFilePath, string ftpMode = PosConst.FTP_CONN_TYPE.PASSIVE)
        {
            bool bRet = false;
            string ftpFileFullPath = string.Format("ftp://{0}/{1}", this.Host, ftpFilePath);
            FtpWebRequest ftpWebRequest = WebRequest.Create(new Uri(ftpFileFullPath)) as FtpWebRequest;
            FtpWebResponse ftpResponse = null;
            try
            {
                ftpWebRequest.Credentials = GetCredentials();
                ftpWebRequest.UseBinary = true;
                ftpWebRequest.UsePassive = (ftpMode == PosConst.FTP_CONN_TYPE.PASSIVE ? true : false);
                ftpWebRequest.KeepAlive = true;
                ftpWebRequest.Method = WebRequestMethods.Ftp.DeleteFile;
                ftpResponse = (FtpWebResponse)ftpWebRequest.GetResponse();

                ftpResponse.Close();
                bRet = true;
            }
            catch (WebException ex)
            {
                ftpResponse = ex.Response as FtpWebResponse;
                if (ftpResponse.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable) bRet = false;
                else bRet = true;
                /* Resource Cleanup */
                //localFileStream.Close();
                //ftpResponse.Close();
                //ftpWebRequest = null;
                return bRet;
            }
            catch (Exception ex)
            {
                UserLog.WriteLogFile(UserCom.LOG_ERROR, System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,
                    "NetworkFtp.Download()", "FTP.Download EXCEPTION=[" + ex.Message);

                ///* Resource Cleanup */
                //localFileStream.Close();
                //if( ftpStream != null) ftpStream.Close();
                //if (ftpResponse != null) ftpResponse.Close();
                //ftpWebRequest = null;

                return bRet = false;
            }

            return bRet;
        }
        #endregion

        #region public bool GetLastModifiedDate(string ftpFilePath)
        public string GetLastModifiedDate(string ftpFilePath)
        {
            DateTime dtModifiedDate;
            string sModifiedDate = "";
            string ftpFileFullPath = string.Format("ftp://{0}{1}", this.Host, ftpFilePath);

            FtpWebRequest ftpWebRequest = WebRequest.Create(new Uri(ftpFileFullPath)) as FtpWebRequest;
            FtpWebResponse ftpResponse = null;

            try
            {
                ftpWebRequest.Credentials = GetCredentials();
                ftpWebRequest.Timeout = 100000;
                //ftpWebRequest.UseBinary = true;
                //ftpWebRequest.UsePassive = true;
                //ftpWebRequest.KeepAlive = true;
                ftpWebRequest.Method = WebRequestMethods.Ftp.GetDateTimestamp;

                ftpResponse = (FtpWebResponse)ftpWebRequest.GetResponse();
                dtModifiedDate = ftpResponse.LastModified;
                sModifiedDate = dtModifiedDate.ToString("yyyyMMddHHmmss");
                
            }
            catch(WebException we)
            {
                String status = ((FtpWebResponse)we.Response).StatusDescription;
            }
            catch(Exception ex)
            {
                
                UserLog.WriteLogFile(UserCom.LOG_ERROR,
                                     System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,      // Project Name (프로젝트명)
                                     System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." +  // Class Name (Class Name (클래스명))
                                     System.Reflection.MethodBase.GetCurrentMethod().Name + "()",                // Function Name (Function Name (함수명))
                                     ex.Message);
            }
            finally
            {
                if (ftpResponse != null)
                    ftpResponse.Close();
            }

            return sModifiedDate;
        }
        #endregion

        /// <summary>
        /// 파일을 FTP 서버에 Download 합니다.
        /// </summary>
        /// <param name="localFileFullPath">로컬 파일의 전체 경로 입니다.</param>
        /// <param name="ftpFilePath"><para>파일을 Download 할 FTP 전체 경로 입니다.</para><para>하위 디렉터리에 넣는 경우 /디렉터리명/파일명.확장자 형태 입니다.</para></param>
        /// <exception cref="FileNotFoundException">지정한 로컬 파일(localFileFullPath)이 없을 때 발생합니다.</exception>
        /// <returns>Download 성공 여부입니다.</returns>
        #region public bool Download(string ftpFilePath, string localFileFullPath)
        public bool Download(string ftpFilePath, string localFileFullPath, string ftpMode = PosConst.FTP_CONN_TYPE.PASSIVE)
        {
            string sMsg = "";
            return Download(ftpFilePath, localFileFullPath, ref sMsg, ftpMode);
        }
        public bool Download(string ftpFilePath, string localFileFullPath, ref string sMsg, string ftpMode = PosConst.FTP_CONN_TYPE.PASSIVE)
        {
            bool bRet = false;
            string ftpFileFullPath = string.Format("ftp://{0}/{1}", this.Host, ftpFilePath);

            UserLog.WriteLogFile(UserCom.LOG_OP, System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,
                           System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." + System.Reflection.MethodBase.GetCurrentMethod().Name + "()",
                           "[FTP URI]" + ftpFileFullPath);
            //string ftpFileFullPath = ftpFilePath;

            //2017.12.05; 미주일경우 FTP 서버에서  ContentLength   응답에 반환 된 데이터가 업거나 서버가 콘텐츠 길이 정보를 보내지 않아 -1 이 오는 현상으로 FileSize 만을 구하는 기능 추가;girak.kim;Start
            long fileSize= 0;
            if (m_cPosStatus.Base.CmpCd.ToUpper().Equals(PosConst.POS_COMPANY_CODE.PCUS))
            {
                fileSize = GetFileSize(ftpFileFullPath);

                UserLog.WriteLogFile(UserCom.LOG_OP, System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,
                          System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." + System.Reflection.MethodBase.GetCurrentMethod().Name + "()",
                          "[fileSize] = " + fileSize.ToString());
            }
            //2017.12.05; 미주일경우 FTP 서버에서  ContentLength   응답에 반환 된 데이터가 업거나 서버가 콘텐츠 길이 정보를 보내지 않아 -1 이 오는 현상으로 FileSize 만을 구하는 기능 추가;girak.kim;End

            FtpWebRequest ftpWebRequest = WebRequest.Create(new Uri(ftpFileFullPath)) as FtpWebRequest;
            FtpWebResponse ftpResponse = null;
            Stream ftpStream = null;
            sMsg = "";
            FileStream localFileStream = null;

            try
            {
                int bufferSize = 8192;
                
                ftpWebRequest.Credentials = GetCredentials();
                ftpWebRequest.UseBinary = true;
                ftpWebRequest.UsePassive = (ftpMode == PosConst.FTP_CONN_TYPE.PASSIVE ? true : false);
                ftpWebRequest.KeepAlive = true;
                ftpWebRequest.Method = WebRequestMethods.Ftp.DownloadFile;

                if (m_delegateFTP != null) FTP.m_delegateFTP(ftpFilePath, 0, 0);

                ftpResponse = (FtpWebResponse)ftpWebRequest.GetResponse();

                //2017.12.05;미주일경우 파일 사이즈 위에서 먼저 구함;girak.kim
                //long svrFileSize = ftpResponse.ContentLength;//원래 소스
                //수정된 내용
                long svrFileSize =0 ;
                if (m_cPosStatus.Base.CmpCd.ToUpper().Equals(PosConst.POS_COMPANY_CODE.PCUS))
                {
                    svrFileSize = fileSize;
                }
                else
                {
                    svrFileSize = ftpResponse.ContentLength;
                }

                ftpStream = ftpResponse.GetResponseStream();

                /* Buffer for the Downloaded Data */
                byte[] byteBuffer = new byte[bufferSize];
                int bytesRead = ftpStream.Read(byteBuffer, 0, bufferSize);
                /* Download the File by Writing the Buffered Data Until the Transfer is Complete */

                /* Open a File Stream to Write the Downloaded File */
                localFileStream = new FileStream(localFileFullPath, FileMode.Create);

                while (bytesRead > 0)
                {
                    localFileStream.Write(byteBuffer, 0, bytesRead);
                    bytesRead = ftpStream.Read(byteBuffer, 0, bufferSize);

                    if ( m_delegateFTP != null) FTP.m_delegateFTP(ftpFilePath, localFileStream.Length, svrFileSize);
                }

                if (localFileStream.Length == svrFileSize && localFileStream.Length > 0) bRet = true;
                else
                {
                    UserLog.WriteLogFile(UserCom.LOG_ERROR, System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,
                        "NetworkFtp.Download()", "file size above!!! SvrFileSize=[" + svrFileSize.ToString() + "], DownFileSize=[" + localFileStream.Length.ToString() + "]");

                    sMsg = "file size above!!! SvrFileSize=[" + svrFileSize.ToString() + "], DownFileSize=[" + localFileStream.Length.ToString() + "]";

                    bRet = false;
                }
            }
            catch (WebException ex)
            {
                ftpResponse = ex.Response as FtpWebResponse;
                //if (ftpResponse.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable) bRet = false;
                //else bRet = true;
                /* Resource Cleanup */
                //localFileStream.Close();
                //ftpResponse.Close();
                //ftpWebRequest = null;
                bRet = false;
                sMsg = ftpFilePath + " " + ex.Message;
                return bRet;
            }
            catch (Exception ex)
            {
                UserLog.WriteLogFile(UserCom.LOG_ERROR, System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,
                    "NetworkFtp.Download()", "FTP.Download EXCEPTION=[" + ex.Message);

                ///* Resource Cleanup */
                //localFileStream.Close();
                //if( ftpStream != null) ftpStream.Close();
                //if (ftpResponse != null) ftpResponse.Close();
                //ftpWebRequest = null;

                sMsg = ftpFilePath + " " + ex.Message;
                return bRet = false;
            }
            finally
            {
                /* Resource Cleanup */
                localFileStream.Close();
                if (ftpStream != null) ftpStream.Close();
                if (ftpResponse != null) ftpResponse.Close();
                ftpWebRequest = null;

                if (!bRet && File.Exists(localFileFullPath)) File.Delete(localFileFullPath); //정상수신 실패시, 다운로드중이던 파일 삭제

                UserLog.WriteLogFile(UserCom.LOG_OP, System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,
                         System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "." + System.Reflection.MethodBase.GetCurrentMethod().Name + "()",
                         "[FTP Download result]" + bRet.ToString());//false 일 경우 error log 참고
            }

            ///* Resource Cleanup */
            //localFileStream.Close();
            //ftpStream.Close();
            //ftpResponse.Close();
            //ftpWebRequest = null;
            //if (!bRet && File.Exists(localFileFullPath)) File.Delete(localFileFullPath); //정상수신 실패시, 다운로드중이던 파일 삭제
            return bRet;
        }
        #endregion


        /// <summary>
        /// 파일을 FTP 서버에 업로드 합니다.
        /// </summary>
        /// <param name="localFileFullPath">로컬 파일의 전체 경로 입니다.</param>
        /// <param name="ftpFilePath"><para>파일을 업로드 할 FTP 전체 경로 입니다.</para><para>하위 디렉터리에 넣는 경우 /디렉터리명/파일명.확장자 형태 입니다.</para></param>
        /// <exception cref="FileNotFoundException">지정한 로컬 파일(localFileFullPath)이 없을 때 발생합니다.</exception>
        /// <returns>업로드 성공 여부입니다.</returns>
        #region public bool Upload(string localFileFullPath, string ftpFilePath)
        public bool Upload(string localFileFullPath, string ftpFilePath, string ftpMode = PosConst.FTP_CONN_TYPE.PASSIVE)
        {
            LocalFileValidationCheck(localFileFullPath);

            //FTPDirectioryCheck(GetDirectoryPath(ftpFilePath));
            //if (IsFTPFileExsit(ftpFilePath))
            //{
            //    throw new ApplicationException(string.Format("{0}은 이미 존재하는 파일 입니다.", ftpFilePath));
            //}

            string ftpFileFullPath = string.Format("ftp://{0}/{1}", this.Host, ftpFilePath);
            FtpWebRequest ftpWebRequest = WebRequest.Create(new Uri(ftpFileFullPath)) as FtpWebRequest;
            ftpWebRequest.Credentials = GetCredentials();
            ftpWebRequest.UseBinary = true;
            ftpWebRequest.UsePassive = (ftpMode == PosConst.FTP_CONN_TYPE.PASSIVE ? true : false);
            ftpWebRequest.Timeout = 10000;
            ftpWebRequest.Method = WebRequestMethods.Ftp.UploadFile;

            FileInfo fileInfo = new FileInfo(localFileFullPath);
            FileStream fileStream = fileInfo.OpenRead();
            Stream stream = null;
            byte[] buf = new byte[2048];
            int currentOffset = 0;
            try
            {
                stream = ftpWebRequest.GetRequestStream();
                currentOffset = fileStream.Read(buf, 0, 2048);
                while (currentOffset != 0)
                {
                    stream.Write(buf, 0, currentOffset);
                    currentOffset = fileStream.Read(buf, 0, 2048);
                }
            }
            catch (Exception ex)
            {
                UserLog.WriteLogFile(UserCom.LOG_ERROR, System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,
                    "NetworkFtp.Upload()", "FTP.Upload EXCEPTION=[" + ex.Message + "]");
                return false;
            }
            finally
            {
                fileStream.Dispose();
                if (stream != null)
                    stream.Dispose();
            }

            return true;
        }
        #endregion

        /// <summary>
        /// 해당 경로에 파일이 존재하는지 여부를 가져옵니다.
        /// </summary>
        /// <param name="ftpFilePath">파일 경로</param>
        /// <returns>존재시 참 </returns>
        #region private bool FTPFileExsit(string ftpFilePath)
        public bool FTPFileExsit(string ftpFilePath, string ftpMode = PosConst.FTP_CONN_TYPE.PASSIVE)
        {
            bool bExisit = false;
            string fileName = GetFileName(ftpFilePath);
            string ftpFileFullPath = string.Format("ftp://{0}{1}", this.Host, GetDirectoryPath(ftpFilePath));
            FtpWebRequest ftpWebRequest = WebRequest.Create(new Uri(ftpFileFullPath)) as FtpWebRequest;
            ftpWebRequest.Credentials = new NetworkCredential(this.UserName, this.Password);
            ftpWebRequest.UseBinary = true;
            ftpWebRequest.UsePassive = (ftpMode == PosConst.FTP_CONN_TYPE.PASSIVE ? true : false);
            ftpWebRequest.Timeout = 10000;
            ftpWebRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

            FtpWebResponse response = null;
            string data = string.Empty;

            try
            {
                response = ftpWebRequest.GetResponse() as FtpWebResponse;
                if (response != null)
                {
                    StreamReader streamReader = new StreamReader(response.GetResponseStream(), Encoding.Default);
                    data = streamReader.ReadToEnd();
                }
            }
            catch (WebException ex)
            {
                response = ex.Response as FtpWebResponse;
                if (response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailableOrBusy) bExisit = false;
                else bExisit = true;
            }
            finally
            {
                if (response != null)
                    response.Close();
            }

            bExisit = false;
            string CRLF = string.Format("{0}", (char)0x0a);
            string[] directorys = data.Split(new string[] { CRLF }, StringSplitOptions.RemoveEmptyEntries);

            foreach (string directory in directorys)
            {
                string[] str = directory.Split(new char[] { ' ' }, System.StringSplitOptions.RemoveEmptyEntries);
                if ((str.Length > 8) && (str[0].Substring(0, 1) != "d") && (str[8] == fileName))
                {
                    bExisit = true;
                    break;
                }
            }

            return bExisit;
        }
        #endregion


        /// <summary>
        /// FTP 풀 경로에서 Directory 경로만 가져옵니다.
        /// </summary>
        /// <param name="ftpFilePath">FTP 풀 경로</param>
        /// <returns>디렉터리 경로입니다.</returns>
        #region private string GetDirectoryPath(string ftpFilePath)
        private string GetDirectoryPath(string ftpFilePath)
        {
            string[] datas = ftpFilePath.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
            string directoryPath = string.Empty;

            for (int i = 0; i < datas.Length - 1; i++)
            {
                directoryPath += string.Format("/{0}", datas[i]);
            }
            return directoryPath;
        }
        #endregion


        /// <summary>
        /// FTP 풀 경로에서 파일이름만 가져옵니다.
        /// </summary>
        /// <param name="ftpFilePath">FTP 풀 경로</param>
        /// <returns>파일명입니다.</returns>
        #region private string GetFileName(string ftpFilePath)
        private string GetFileName(string ftpFilePath)
        {
            string[] datas = ftpFilePath.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
            return datas[datas.Length - 1];
        }
        #endregion


        /// <summary>
        /// FTP 경로의 디렉토리를 점검하고 없으면 생성
        /// </summary>
        /// <param name="directoryPath">디렉터리 경로 입니다.</param>
        #region public void FTPDirectioryCheck(string directoryPath)
        public void FTPDirectioryCheck(string directoryPath)
        {

            string[] directoryPaths = directoryPath.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
            string currentDirectory = string.Empty;
            foreach (string directory in directoryPaths)
            {
                currentDirectory += string.Format("/{0}", directory);
                if (!IsExtistDirectory(currentDirectory))
                {
                    MakeDirectory(currentDirectory);
                }
            }
        }
        #endregion



        /// <summary>
        /// FTP에 해당 디렉터리가 있는지 알아온다.
        /// </summary>
        /// <param name="currentDirectory">디렉터리 명</param>
        /// <returns>있으면 참</returns>
        #region private bool IsExtistDirectory(string currentDirectory)
        private bool IsExtistDirectory(string currentDirectory, string ftpMode = PosConst.FTP_CONN_TYPE.PASSIVE)
        {

            string ftpFileFullPath = string.Format("ftp://{0}{1}", this.Host, GetParentDirectory(currentDirectory));
            FtpWebRequest ftpWebRequest = WebRequest.Create(new Uri(ftpFileFullPath)) as FtpWebRequest;
            ftpWebRequest.Credentials = new NetworkCredential(this.UserName, this.Password);
            ftpWebRequest.UseBinary = true;
            ftpWebRequest.UsePassive = (ftpMode == PosConst.FTP_CONN_TYPE.PASSIVE ? true : false);
            ftpWebRequest.Timeout = 10000;
            ftpWebRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
            FtpWebResponse response = null;
            string data = string.Empty;

            try
            {
                response = ftpWebRequest.GetResponse() as FtpWebResponse;
                if (response != null)
                {
                    StreamReader streamReader = new StreamReader(response.GetResponseStream(), Encoding.Default);
                    data = streamReader.ReadToEnd();
                }
            }

            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }

            string[] directorys = data.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
            return (from directory in directorys
                    select directory.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries)
                        into directoryInfos
                        where directoryInfos[0][0] == 'd'
                        select directoryInfos[8]).Any(
                        name => name == (currentDirectory.Split('/')[currentDirectory.Split('/').Length - 1]).ToString());
        }
        #endregion

        /// <summary>
        /// 상위 디렉터리를 알아옵니다.
        /// </summary>
        /// <param name="currentDirectory"></param>
        /// <returns></returns>
        #region private string GetParentDirectory(string currentDirectory)
        private string GetParentDirectory(string currentDirectory)
        {
            string[] directorys = currentDirectory.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
            string parentDirectory = string.Empty;
            for (int i = 0; i < directorys.Length - 1; i++)
            {
                parentDirectory += "/" + directorys[i];
            }

            return parentDirectory;
        }
        #endregion


        /// <summary>
        /// 인증을 가져옵니다.
        /// </summary>
        /// <returns>인증</returns>
        private ICredentials GetCredentials()
        {
            return new NetworkCredential(this.UserName, this.Password);
        }

        private string GetStringResponse(FtpWebRequest ftp)
        {
            string result = "";
            using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse())
            {

                long size = response.ContentLength;
                using (Stream datastream = response.GetResponseStream())
                {
                    if (datastream != null)
                    {
                        using (StreamReader sr = new StreamReader(datastream))
                        {
                            result = sr.ReadToEnd();
                            sr.Close();
                        }
                        datastream.Close();
                    }
                }
                response.Close();
            }
            return result;
        }

        private FtpWebRequest GetRequest(string URI)
        {
            FtpWebRequest result = (FtpWebRequest)WebRequest.Create(URI);
            result.Credentials = GetCredentials();
            result.KeepAlive = false;
            return result;
        }

        /// <summary>
        /// FTP에 해당 디렉터리를 만든다.
        /// </summary>
        /// <param name="dirpath"></param>
        #region public bool MakeDirectory(string dirpath)
        public bool MakeDirectory(string dirpath)
        {

            string URI = string.Format("ftp://{0}/{1}", this.Host, dirpath);
            System.Net.FtpWebRequest ftp = GetRequest(URI);
            ftp.Method = System.Net.WebRequestMethods.Ftp.MakeDirectory;

            try
            {
                string str = GetStringResponse(ftp);
            }
            catch
            {
                return false;
            }
            return true;
        }
        #endregion


        /// <summary>
        /// 지정한 로컬 파일이 실제 존재하는지 확인합니다.
        /// </summary>
        /// <param name="localFileFullPath">로컬 파일의 전체 경로입니다.</param>
        #region private void LocalFileValidationCheck(string localFileFullPath)
        private void LocalFileValidationCheck(string localFileFullPath)
        {
            if (!File.Exists(localFileFullPath))
            {
                throw new FileNotFoundException(string.Format("No local file specified.\npath : {0}", localFileFullPath));
            }
        }
        #endregion


        /// <summary>
        /// FTP 서버에 지정한 파일의 생성일자를 가져 온다.
        /// </summary>
        /// <param name="ftpFileCreateDateCheck">로컬 파일의 전체 경로입니다.</param>
        #region private void ftpFileCreateDateCheck(string ftpFilePath, string ftpFileName)
        public string ftpFileCreateDateCheck(string ftpFilePath, string ftpFileName, string ftpMode)
        {
            string sCreateDate = string.Empty;
            //string sRet = UserCom.RST_ERR;
            //bool bExisit = false;

            string fileName = GetFileName(ftpFilePath);
            string ftpFileFullPath = string.Format("ftp://{0}{1}", this.Host, GetDirectoryPath(ftpFilePath));
            FtpWebRequest ftpWebRequest = WebRequest.Create(new Uri(ftpFileFullPath)) as FtpWebRequest;
            //FtpWebRequest ftpWebRequest = WebRequest.Create(new Uri(ftpFilePath)) as FtpWebRequest;

            ftpWebRequest.Credentials = new NetworkCredential(this.UserName, this.Password);
            ftpWebRequest.UseBinary = true;
            ftpWebRequest.UsePassive = (ftpMode == PosConst.FTP_CONN_TYPE.PASSIVE ? true : false);
            ftpWebRequest.Timeout = 10000;
            ftpWebRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

            //ftpWebRequest.Method = WebRequestMethods.Ftp.GetDateTimestamp;

            FtpWebResponse response = null;
            string data = string.Empty;

            try
            {
                response = ftpWebRequest.GetResponse() as FtpWebResponse;
                if (response != null)
                {
                    StreamReader streamReader = new StreamReader(response.GetResponseStream(), Encoding.Default);
                    data = streamReader.ReadToEnd();
                }
            }
            catch (WebException ex)
            {
                response = ex.Response as FtpWebResponse;
                //if (response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailableOrBusy) bExisit = false;
                //else bExisit = true;
            }
            finally
            {
                if (response != null)
                    response.Close();
            }

            //bExisit = false;
            string CRLF = string.Format("{0}", (char)0x0a);
            string[] directorys = data.Split(new string[] { CRLF }, StringSplitOptions.RemoveEmptyEntries);

            foreach (string directory in directorys)
            {
                string[] str = directory.Split(new char[] { ' ' }, System.StringSplitOptions.RemoveEmptyEntries);
                if ((str.Length > 8) && (str[0].Substring(0, 1) != "d") && (str[8].Replace("\r", "") == fileName))
                {
                    //bExisit = true;
                    sCreateDate = str[5] + "|" + str[6] + "|" + str[7];
                    break;
                }
            }

            //return bExisit;
            return sCreateDate;

        }
        #endregion
         

        //2017.12.05;FTP 서버 파일 사이즈만 구하는 기능;girak.kim;미주 서버에서 ftp contentLength 응답 결과가 -1 로 내려오는 문제로 기능 추가함
        /// <summary>
        /// FTP 서버 파일 사이즈를 구해온다.
        /// </summary>
        /// <param name="URI"></param>
        /// <returns></returns>
        private long GetFileSize(string URI)
        {
            long fileSize = 0;
            try
            {

                //FtpWebRequest ftpWebReq = (FtpWebRequest)WebRequest.Create(URI); 속도가 조금 안 좋은듯...
                FtpWebRequest ftpWebReq = WebRequest.Create(URI) as FtpWebRequest;
                ftpWebReq.Credentials = GetCredentials();
                ftpWebReq.Method = WebRequestMethods.Ftp.GetFileSize;
                ftpWebReq.KeepAlive = true;
                FtpWebResponse ftpWebResp = ftpWebReq.GetResponse() as FtpWebResponse;
                fileSize = ftpWebResp.ContentLength;
                
                ftpWebResp.Close();                

            }
            catch(Exception ex)
            {
                fileSize = -1;
                UserLog.WriteLogFile(UserCom.LOG_ERROR, System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name,
                   "NetworkFtp.GetFileSize()", "FTP.GetFileSize EXCEPTION=[" + ex.Message);
            }
            return fileSize;
        }

        #endregion
    }

    /// <summary>
    /// Fluent FTP를 위한 유틸 클래스입니다.
    /// </summary>
    class FTPEx
    {
        #region 클래스 변수
        /// <summary>
        /// FTP 서버 호스트명(IP)
        /// </summary>
        private string m_sHost;
        public string Host { get { return m_sHost; } set { m_sHost = value; } }

        /// <summary>
        /// FTP 서버 Port
        /// </summary>
        private int m_iPort;
        public int Port { get { return m_iPort; } set { m_iPort = value; } }

        /// <summary>
        /// FTP 사용자 명
        /// </summary>
        private string m_sUserName;
        public string UserName { get { return m_sUserName; } set { m_sUserName = value; } }

        /// <summary>
        /// FTP 비밀번호
        /// </summary>
        private string m_sPassword;
        public string Password { get { return m_sPassword; } set { m_sPassword = value; } }
        #endregion

        #region 생성자
        public FTPEx(string sHost, int iPort, string sUserName, string sPassword)
        {
            Host = sHost;
            Port = iPort;
            UserName = sUserName;
            Password = sPassword;
        }
        #endregion
    }
}
