using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
namespace AIMSExtension
{
    /// 
    /// ftp下载类
    /// 
    public class FTPTransmission
    {
        /// 
        /// 记录所有要下载的文件路径及下载到本地的路径
        /// 
        public static List ListFileDirectory = new List();
        /// 
        /// 记录当前文件路径及下载到本地的路径
        /// 
        public static List nowListFileDirectory = new List();
        /// 
        /// 记录要下载的文件路径及下载到本地的路径
        /// 
        public struct ftpFileDirectory
        {
            /// 
            /// 要下载的文件路径
            /// 
            public string ftpPath;
            /// 
            /// 下载到本地的路径
            /// 
            public string localPath;
            /// 
            /// 文件名
            /// 
            public string filename;
            /// 
            /// 文件大小
            /// 
            public long filelength;
            /// 
            /// MD5码
            /// 
            public string MD5Hash;
        }
        /// 
        /// 设置ftp服务器的命令,并获取文件和文件夹,以及文件夹内的子文件
        /// 
        /// FTP地址路径
        /// 要发送到FTP服务器的命令
        /// 用户名
        /// 密码
        /// 
        public static string[] ftp(string ftpads, string type, string username, string password)
        {
            WebResponse webresp = null;
            StreamReader ftpFileListReader = null;
            FtpWebRequest ftpRequest = null;
            try
            {
                ftpRequest = (FtpWebRequest)WebRequest.Create(new Uri(ftpads));
                ftpRequest.Method = type;
                ftpRequest.Credentials = new NetworkCredential(username,
                                                          password);
                webresp = ftpRequest.GetResponse();
                ftpFileListReader = new StreamReader(webresp.GetResponseStream(), Encoding.UTF8);//new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default)
                StringBuilder str = new StringBuilder();
                string line = ftpFileListReader.ReadLine();
                while (line != null)
                {
                    str.Append(line);
                    str.Append("\n");
                    line = ftpFileListReader.ReadLine();
                }
                string[] fen = str.ToString().Split('\n');
                return fen;
            }
            catch (Exception)
            {
                //MessageBox.Show("更新失败! 请检查网络或者FTP用户名与口令!");
                Environment.Exit(0);
                return null;
            }
        }
        /// 
        /// 递归实现获取ftp目录下所有文件及文件夹以及文件夹内的子文件
        /// 
        /// FTP路径
        /// 保存的本地路径
        /// 用户名
        /// 密码
        public static void downftp(string ftpads, string downloadDir, string username, string password, Hashtable htUpdateFile)
        {
            try
            {
                downloadDir = downloadDir.Replace("\\\\", "\\");
                string ftpdir = ftpads;
                string[] fullname = ftp(ftpads, WebRequestMethods.Ftp.ListDirectoryDetails, username, password);
                if (fullname == null) return;
                string[] onlyname = ftp(ftpads, WebRequestMethods.Ftp.ListDirectory, username, password);
                if (onlyname == null) return;
                if (!Directory.Exists(downloadDir))
                {
                    Directory.CreateDirectory(downloadDir);
                }
                foreach (string names in fullname)
                {
                    //判断是否具有文件夹标识
                    if (names.Contains(""))
                    {
                        string olname = names.Split(new string[] { "" },
                        StringSplitOptions.None)[1].Trim();
                        downftp(ftpads + "/" + olname, downloadDir + "\\" + olname, username, password, htUpdateFile);
                    }
                    else
                    {
                        foreach (string onlynames in onlyname)
                        {
                            if (string.IsNullOrEmpty(onlynames.Trim()) || string.IsNullOrEmpty(names.Trim())) break;
                            if (names.Contains(" " + onlynames))
                            {
                                //download(downloadDir + "\\" + onlynames, ftpads + "/" + onlynames, username, password);
                                var fd = new ftpFileDirectory();
                                fd.ftpPath = ftpads + "/" + onlynames.ToString();
                                fd.localPath = downloadDir + "\\" + onlynames.ToString();
                                fd.localPath = fd.localPath.Replace("\\\\", "\\");
                                fd.filename = onlynames.ToString();
                                fd.filelength = GetFileSize(fd.ftpPath, username, password);
                                for (int i = 0; i < htUpdateFile.Count; i++)
                                {
                                    string[] fileArray = (string[])htUpdateFile[i];
                                    if (fd.filename == fileArray[0])
                                    {
                                        fd.MD5Hash = fileArray[1];
                                        break;
                                    }
                                }
                                ListFileDirectory.Add(fd);
                                break;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                PublicMethod.WriteLog(ex);
                Environment.Exit(0);
            }
        }
        /// 
        /// 递归实现获取ftp目录下所有文件及文件夹以及文件夹内的子文件
        /// 
        /// FTP路径
        /// 保存的本地路径
        /// 用户名
        /// 密码
        public static void downNow(string ftpads)
        {
            try
            {
                DirectoryInfo theFolder = new DirectoryInfo(ftpads);
                printAllFile(theFolder);
            }
            catch (Exception ex)
            {
                //MessageBox.Show("获取目录失败+downftp" + ex.ToString());
                Environment.Exit(0);
            }
        }
        public static void printAllFile(DirectoryInfo di)
        {
            FileInfo[] fiArray = di.GetFiles();
            DirectoryInfo[] diArray = di.GetDirectories();
            foreach (FileInfo NextFile in fiArray)
            {
                try
                {
                    if (NextFile.Name.Contains("AutoUpdate") || NextFile.Name.Contains("KHD_ICUEMR")) continue;
                    var fd = new ftpFileDirectory();
                    fd.ftpPath = NextFile.DirectoryName + "\\" + NextFile.Name.ToString();
                    fd.filename = NextFile.Name.ToString();
                    fd.filelength = NextFile.Length;
                    fd.MD5Hash = GetMD5HashFromFile(fd.ftpPath);
                    nowListFileDirectory.Add(fd);
                }
                catch (Exception)
                {
                    continue;
                }
            }
            foreach (DirectoryInfo inst in diArray)
            {
                printAllFile(inst);
            }
        }
        /// 
        /// 单个文件下载
        /// 
        /// 保存文件的本地路径
        /// 下载文件的FTP路径
        /// 用户名
        /// 密码
        public static void download(string adss, string ftpadss, string username, string password)
        {
            try
            {
                //FileMode常数确定如何打开或创建文件,指定操作系统应创建新文件。
                FtpWebRequest downRequest = (FtpWebRequest)WebRequest.Create(new Uri(ftpadss));
                downRequest.Credentials = new NetworkCredential(username, password);
                //设置要发送到 FTP 服务器的命令
                downRequest.Method = WebRequestMethods.Ftp.DownloadFile;
                FtpWebResponse response = (FtpWebResponse)downRequest.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);
                if (readCount > 0)
                {
                    //FileMode.Create如果文件已存在,它将被改写
                    FileStream outputStream = new FileStream(adss, FileMode.Create);
                    while (readCount > 0)
                    {
                        outputStream.Write(buffer, 0, readCount);
                        readCount = ftpStream.Read(buffer, 0, bufferSize);
                    }
                    outputStream.Close();
                }
                ftpStream.Close();
                response.Close();
            }
            catch (Exception)
            {
            }
        }
        /// 
        /// 获得文件大小
        /// 
        /// 
        /// 
        public static long GetFileSize(string ftpadss, string username, string password)
        {
            long fileSize = 0;
            try
            {
                FtpWebRequest downRequest = (FtpWebRequest)WebRequest.Create(new Uri(ftpadss));
                downRequest.Credentials = new NetworkCredential(username, password);
                downRequest.Method = WebRequestMethods.Ftp.GetFileSize;
                FtpWebResponse response = (FtpWebResponse)downRequest.GetResponse();
                fileSize = response.ContentLength;
                response.Close();
            }
            catch (Exception e)
            {
                PublicMethod.WriteLog(e);
            }
            return fileSize;
        }
        ///   
        /// FTP获取文件的MD5码  
        ///   
        /// 传入的文件名(含路径及后缀名)  
        ///   
        public static string FTPGetMD5HashFromFile(string fileName)
        {
            try
            {
                FileStream file = new FileStream(fileName, System.IO.FileMode.Open);
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(file);
                file.Close();
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++)
                {
                    sb.Append(retVal[i].ToString("x2"));
                }
                return sb.ToString();
            }
            catch (Exception  )
            {
                return "";
                //throw new Exception("GetMD5HashFromFile() fail,error:" + ex.Message);
            }
        }
        ///   
        /// 获取文件的MD5码  
        ///   
        /// 传入的文件名(含路径及后缀名)  
        ///   
        public static string GetMD5HashFromFile(string fileName)
        {
            try
            {
                FileStream file = new FileStream(fileName, System.IO.FileMode.Open);
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(file);
                file.Close();
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++)
                {
                    sb.Append(retVal[i].ToString("x2"));
                }
                return sb.ToString();
            }
            catch (Exception)
            {
                //throw new Exception("GetMD5HashFromFile() fail,error:" + ex.Message);
                return "";
            }
        }
          
        #region 上传文件 UploadFile
        /// 
        /// 上传文件
        /// 
        /// 需要上传的文件
        /// 目标路径
        /// ftp地址
        /// ftp用户名
        /// ftp密码
        public static void UploadFile(FileInfo fileinfo, string targetDir, string hostname, string username, string password)
        {
            //1. check target
            string target;
            if (targetDir.Trim() == "")
            {
                return;
            }
            target = Guid.NewGuid().ToString();  //使用临时文件名
            string URI = "FTP://" + hostname + "/" + targetDir + "/" + target;
            if (targetDir == "PDF" || targetDir == "JPG" )
            {
                URI = "FTP://" + hostname + "/" + target;
            }
            ///WebClient webcl = new WebClient();
           System.Net.FtpWebRequest  ftp = GetRequest(URI, username, password);
            try
            {
                System.Net.FtpWebRequest ftpdel = GetRequest(("FTP://" + hostname + "/" + fileinfo.Name), username, password);
                ftpdel.Method = System.Net.WebRequestMethods.Ftp.DeleteFile; //删除
                ftpdel.GetResponse();
            }
            catch (Exception)
            { 
            }
            ftp = GetRequest(URI, username, password);
            //设置FTP命令 设置所要执行的FTP命令,
            //ftp.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails;//假设此处为显示指定路径下的文件列表
            ftp.Method = System.Net.WebRequestMethods.Ftp.UploadFile;
            //指定文件传输的数据类型
            ftp.UseBinary = true;
            ftp.UsePassive = true;
            //告诉ftp文件大小
            ftp.ContentLength = fileinfo.Length;
            //缓冲大小设置为2KB
            const int BufferSize = 2048;
            byte[] content = new byte[BufferSize - 1 + 1];
            int dataRead;
            //打开一个文件流 (System.IO.FileStream) 去读上传的文件
            using (FileStream fs = fileinfo.OpenRead())
            {
                try
                {
                    //把上传的文件写入流
                    using (Stream rs = ftp.GetRequestStream())
                    {
                        do
                        {
                            //每次读文件流的2KB
                            dataRead = fs.Read(content, 0, BufferSize);
                            rs.Write(content, 0, dataRead);
                        } while (!(dataRead < BufferSize));
                        rs.Close();
                    }
                }
                catch (Exception) { }
                finally
                {
                    fs.Close();
                }
            }
            ftp = null;
            //设置FTP命令
            ftp = GetRequest(URI, username, password);
            ftp.Method = System.Net.WebRequestMethods.Ftp.Rename; //改名
            ftp.RenameTo = fileinfo.Name;
            try
            {
                ftp.GetResponse();
            }
            catch (Exception ex)
            {
                ftp = GetRequest(URI, username, password);
                ftp.Method = System.Net.WebRequestMethods.Ftp.DeleteFile; //删除
                ftp.GetResponse();
                throw ex;
            }
            finally
            {
                //fileinfo.Delete();
            }
            // 可以记录一个日志  "上传" + fileinfo.FullName + "上传到" + "FTP://" + hostname + "/" + targetDir + "/" + fileinfo.Name + "成功." );
            ftp = null;
            #region
            /*****
             *FtpWebResponse
             * ****/
            //FtpWebResponse ftpWebResponse = (FtpWebResponse)ftp.GetResponse();
            #endregion
        }
        public static void UploadFile(FileInfo fileinfo, string targetDir, string hostname, string username, string password, string FileName)
        {
            //1. check target
            string target;
            if (targetDir.Trim() == "")
            {
                return;
            }
            target = Guid.NewGuid().ToString();  //使用临时文件名
            string URI = "FTP://" + hostname + "/" + targetDir + "/" + target;
            if (targetDir == "PDF" || targetDir == "JPG")
            {
                URI = "FTP://" + hostname + "/" + target;
            }
            ///WebClient webcl = new WebClient();
            System.Net.FtpWebRequest ftp = GetRequest(URI, username, password);
            try
            {
                System.Net.FtpWebRequest ftpdel = GetRequest(("FTP://" + hostname + "/" + FileName), username, password);
                ftpdel.Method = System.Net.WebRequestMethods.Ftp.DeleteFile; //删除
                ftpdel.GetResponse();
            }
            catch (Exception)
            {
            }
            ftp = GetRequest(URI, username, password);
            //设置FTP命令 设置所要执行的FTP命令,
            //ftp.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails;//假设此处为显示指定路径下的文件列表
            ftp.Method = System.Net.WebRequestMethods.Ftp.UploadFile;
            //指定文件传输的数据类型
            ftp.UseBinary = true;
            ftp.UsePassive = true;
            //告诉ftp文件大小
            ftp.ContentLength = fileinfo.Length;
            //缓冲大小设置为2KB
            const int BufferSize = 2048;
            byte[] content = new byte[BufferSize - 1 + 1];
            int dataRead;
            //打开一个文件流 (System.IO.FileStream) 去读上传的文件
            using (FileStream fs = fileinfo.OpenRead())
            {
                try
                {
                    //把上传的文件写入流
                    using (Stream rs = ftp.GetRequestStream())
                    {
                        do
                        {
                            //每次读文件流的2KB
                            dataRead = fs.Read(content, 0, BufferSize);
                            rs.Write(content, 0, dataRead);
                        } while (!(dataRead < BufferSize));
                        rs.Close();
                    }
                }
                catch (Exception) { }
                finally
                {
                    fs.Close();
                }
            }
            ftp = null;
            //设置FTP命令
            ftp = GetRequest(URI, username, password);
            ftp.Method = System.Net.WebRequestMethods.Ftp.Rename; //改名
            ftp.RenameTo = FileName;
            try
            {
                ftp.GetResponse();
            }
            catch (Exception ex)
            {
                ftp = GetRequest(URI, username, password);
                ftp.Method = System.Net.WebRequestMethods.Ftp.DeleteFile; //删除
                ftp.GetResponse();
                throw ex;
            }
            finally
            {
                //fileinfo.Delete();
            }
            // 可以记录一个日志  "上传" + fileinfo.FullName + "上传到" + "FTP://" + hostname + "/" + targetDir + "/" + FileName + "成功." );
            ftp = null;
            #region
            /*****
             *FtpWebResponse
             * ****/
            //FtpWebResponse ftpWebResponse = (FtpWebResponse)ftp.GetResponse();
            #endregion
        }
        private static FtpWebRequest GetRequest(string URI, string username, string password)
        {
            //根据服务器信息FtpWebRequest创建类的对象
            FtpWebRequest result = (FtpWebRequest)FtpWebRequest.Create(URI);
            //提供身份验证信息
            result.Credentials = new System.Net.NetworkCredential(username, password);
            //设置请求完成之后是否保持到FTP服务器的控制连接,默认值为true
            result.KeepAlive = false;
            return result;
        }
        #endregion
    }
}