FtpWebRequest FTP异步下载、异步上传文件

异步下载:

public interface IPrimaryKey<T>
    {
        T GetKey();
    }

    public class DownloadInfo : IPrimaryKey<string>
    {
        public string FtpResourceFilePath { get; set; }

        public string FileSaveLocalPath { get; set; }

        public bool IsDir { get; set; }

        public DateTime StartTime { get; set; }

        public int ProgressPercentage { get; set; }

        public string Speed { get; set; }

        public string GetKey()
        {
            return this.FtpResourceFilePath;
        }

        public List<DownloadInfo> SubFiles { get; set; }
    }
    class Program
    {
        static readonly string FTP_USERNAME = string.Empty;
        static readonly string FTP_PASSWORD = string.Empty;
        static readonly string FTP_DOMAIN = string.Empty;
        // default 1 seconds.
        static readonly int FTP_REQUEST_TIMEOUT = 1;
        // default 1 seconds.
        static readonly int FTP_REQUEST_READWRITERTIMEOUT = 1;

        static Program()
        {
            FTP_REQUEST_TIMEOUT = Convert.ToInt32(ConfigurationManager.AppSettings.Get("FTP.Request.Timeout"));
            FTP_REQUEST_READWRITERTIMEOUT = Convert.ToInt32(ConfigurationManager.AppSettings.Get("FTP.Request.ReadWriteTimeout"));
            FTP_USERNAME = ConfigurationManager.AppSettings.Get("FTP.UserName");
            FTP_PASSWORD = ConfigurationManager.AppSettings.Get("FTP.Password");
            FTP_DOMAIN = ConfigurationManager.AppSettings.Get("FTP.Domain");
        }

        static int DownloadCount = 0;
        static int CompleteCount = 0;

        static void Main(string[] args)
        {
            // default max parallel connection count is two in the .net framework.
            // sugesstion no over 1024.
            // and you also can add config node in app.config
            /* <configuration>
             *  <system.net>
             *      <connectionManagement>
             *          <add address="*" maxconnection="512"/>
             *      </connectionManagement>
             *  </system>
             * </configuration>
             */
            //System.Net.ServicePointManager.DefaultConnectionLimit = 512;

            string localRootPath = ConfigurationManager.AppSettings.Get("SaveRootPath");

            List<DownloadInfo> rootFiles = GetSubFilesList(new DownloadInfo()
            {
                FtpResourceFilePath = "ftp://172.21.3.17//dd/MR",
                FileSaveLocalPath = string.Concat(localRootPath, "~TEMP\Test1")
            });

            DownloadFilesAsync(rootFiles);

            Console.ReadKey();
        }

        private static void DownloadFilesAsync(List<DownloadInfo> items)
        {
            foreach (DownloadInfo task in items)
            {
                task.StartTime = DateTime.Now;

                if (task.IsDir)
                {
                    task.SubFiles = GetSubFilesList(task);

                    DownloadFilesAsync(task.SubFiles);
                }
                else
                {
                    // try create the directory before donwload.
                    TryCreateDirectory(task.FileSaveLocalPath);

                    // Uri      :the resource paht which will be download.
                    // fileName :the dowload file save path;
                    CreateWebClient().DownloadFileAsync(new Uri(task.FtpResourceFilePath), task.FileSaveLocalPath, task);
                }
            }
        }

        static WebClient CreateWebClient()
        {
        // 限制最多同时现在的线程数
        LimitThreadAgain:
            if (DownloadCount - CompleteCount > 300)
            {
                Thread.Sleep(5000);

                goto LimitThreadAgain;
            }

            DownloadCount++;

            WebClient client = new WebClient();
            client.Credentials = new NetworkCredential(FTP_USERNAME, FTP_PASSWORD, FTP_DOMAIN);
            client.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(client_DownloadFileCompleted);
            client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);

            return client;
        }

        private static List<DownloadInfo> GetSubFilesList(DownloadInfo task)
        {
            List<DownloadInfo> subFiles = new List<DownloadInfo>();

            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(task.FtpResourceFilePath));
            request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
            request.Credentials = new NetworkCredential(FTP_USERNAME, FTP_PASSWORD, FTP_DOMAIN);
            request.UseBinary = true;
            request.Timeout = FTP_REQUEST_TIMEOUT;
            request.ReadWriteTimeout = FTP_REQUEST_READWRITERTIMEOUT;

            using (WebResponse response = request.GetResponse())
            {
                using (StreamReader responseStream = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default))
                {
                    string line = responseStream.ReadLine();
                    while (line != null)
                    {
                        Console.WriteLine(line);

                        string[] lineParitialArray = line.Split(new char[] { ' ' });
                        string theName = lineParitialArray[lineParitialArray.Length - 1];

                        if (line.IndexOf("<DIR>") != -1)
                        {
                            subFiles.Add(new DownloadInfo()
                            {
                                FtpResourceFilePath = string.Concat(task.FtpResourceFilePath, "/", theName),
                                FileSaveLocalPath = string.Concat(task.FileSaveLocalPath, "\", theName),
                                IsDir = true
                            });
                        }
                        else
                        {
                            subFiles.Add(new DownloadInfo()
                            {
                                FtpResourceFilePath = string.Concat(task.FtpResourceFilePath, "/", theName),
                                FileSaveLocalPath = string.Concat(task.FileSaveLocalPath, "\", theName),
                                IsDir = false
                            });
                        }

                        line = responseStream.ReadLine();
                    }
                }
            }

            return subFiles;
        }

        static void TryCreateDirectory(string filePath)
        {
            FileInfo fileInfo = new FileInfo(filePath);
            if (!fileInfo.Directory.Exists)
            {
                try
                {
                    fileInfo.Directory.Create();
                }
                catch (Exception ex)
                {
                    Logger.Current.Error("an error thrown while create directory:
{0}
{1}", ex.Message, ex.StackTrace);
                }
            }
        }

        static void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            DownloadInfo downloadInfo = e.UserState as DownloadInfo;

            downloadInfo.ProgressPercentage = e.ProgressPercentage;
            double downloadTime = (DateTime.Now - downloadInfo.StartTime).TotalSeconds;
            downloadInfo.Speed = GetFriendlyFileSize(e.BytesReceived / downloadTime, 2);

            Console.WriteLine("download precentage:{0}-{1}-{2}", downloadInfo.ProgressPercentage, downloadInfo.Speed, downloadInfo.FtpResourceFilePath);

            Logger.Current.Debug(string.Format("download precentage:{0}-{1}-{2}", downloadInfo.ProgressPercentage, downloadInfo.Speed, downloadInfo.FtpResourceFilePath));
        }

        static void client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                if (e.Error.InnerException != null)
                    Logger.Current.Error(string.Format("download error:{0}
{1}", e.Error.InnerException.Message, e.Error.InnerException.StackTrace));
                else
                    Logger.Current.Error(string.Format("download error:{0}
{1}", e.Error.Message, e.Error.StackTrace));
            }

            DownloadInfo downloadInfo = e.UserState as DownloadInfo;

            Console.WriteLine("download complete:{0}", downloadInfo.FtpResourceFilePath);
            Logger.Current.Debug(string.Format("download complete:{0}", downloadInfo.FtpResourceFilePath));

            CompleteCount++;
        }

        const double KB = 1024;
        const double MR = KB * 1024;
        const double GB = MR * 1024;
        const double TB = MR * 1024;
        const double PB = TB * 1024;

        static string GetFriendlyFileSize(double size, int decimals)
        {
            if (KB > size)
                return string.Format("{0}B", Math.Round(size, decimals));
            else if (MR > size)
                return string.Format("{0}KB", Math.Round(size / KB, decimals));
            else if (GB > size)
                return string.Format("{0}MR", Math.Round(size / MR, decimals));
            else if (TB > size)
                return string.Format("{0}GB", Math.Round(size / GB, decimals));
            else if (PB > size)
                return string.Format("{0}TB", Math.Round(size / TB, decimals));
            else
                return string.Format("{0}PB", Math.Round(size / PB, decimals));
        }
}

异步上传:

// uploading
#region uploading

public class Program
{
    public static void Main(string[] args)
    {
        FtpState state = new FtpState();

        // the ftp url scheme like: ftp://
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri("ftp://172.21.*.1*//dd/SHFBGuidedInstaller_2014.5.31.0.zip"));
        request.Method = WebRequestMethods.Ftp.UploadFile;
        //request.Method = WebRequestMethods.Ftp.DownloadFile;

        request.Credentials = new NetworkCredential("dn", "new.1234", "domain");

        state.Request = request;
        state.FileName = @"C:UsersdnDesktopSHFBGuidedInstaller_2014.5.31.0.zip";
        //state.FileName = @"C:UsersdnDesktopMRSHFBGuidedInstaller_2014.5.31.0.zip";

        // 获得WaitOne()对象
        ManualResetEvent waitOjbect = state.OperationComplete;

        // 开始异步获取数据流
        request.BeginGetRequestStream(
            new AsyncCallback(EndGetStreamCallback),
            state
            );

        // 线程等待
        waitOjbect.WaitOne();

        if (state.OperationException != null)
        {
            throw state.OperationException;
        }
        else
        {
            Console.WriteLine("操作已经完成!");
        }
   }

       public class FtpState
       {
            private ManualResetEvent wait;
            private FtpWebRequest request;
            private string fileName;
            private Exception opreationException = null;
            private string statusDescription;

            public FtpState()
            {
                wait = new ManualResetEvent(false);
            }

            public ManualResetEvent OperationComplete
            {
                get { return wait; }
            }

            public FtpWebRequest Request
            {
                get { return request; }
                set { request = value; }
            }

            public string FileName
            {
                get { return fileName; }
                set { fileName = value; }
            }

            public Exception OperationException
            {
                get { return opreationException; }
                set { opreationException = value; }
            }

            public string StatusDescription
            {
                get { return statusDescription; }
                set { statusDescription = value; }
            }
        }

        private static void EndGetStreamCallback(IAsyncResult result)
        {
            FtpState state = (FtpState)result.AsyncState;

            try
            {
                using (Stream requestStream = state.Request.EndGetRequestStream(result))
                {
                    const int bufferLength = 2048;
                    byte[] buffer = new byte[bufferLength];

                    int count = 0;
                    int readBytes = 0;

                    using (FileStream stream = File.OpenRead(state.FileName))
                    {
                        do
                        {
                            readBytes = stream.Read(buffer, 0, bufferLength);

                            requestStream.Write(buffer, 0, readBytes);

                            count += readBytes;
                        }
                        while (readBytes != 0);
                    }

                    Console.WriteLine("写入{0}字节到数据流中", count);

                    state.Request.BeginGetResponse(new AsyncCallback(EndGetResponseCallback), state);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("请求数据流失败!");

                state.OperationException = ex;
                state.OperationComplete.Set();
            }
        }

        private static void EndGetResponseCallback(IAsyncResult result)
        {
            FtpState state = (FtpState)result.AsyncState;

            try
            {
                FtpWebResponse response = (FtpWebResponse)state.Request.EndGetResponse(result);
                response.Close();

                state.StatusDescription = response.StatusDescription;
                // 标记主线程结束
                state.OperationComplete.Set();
            }
            catch (Exception ex)
            {
                Console.WriteLine("获取请求回应失败!");
                state.OperationException = ex;
                state.OperationComplete.Set();
            }
        }

        #endregion
}
原文地址:https://www.cnblogs.com/yy3b2007com/p/4629335.html