zoukankan      html  css  js  c++  java
  • 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
    }
  • 相关阅读:
    Vim Reference
    Java 8 Consumer、Supplier、Predicate、Function
    Java 8 Stream 用法
    Java 基础 Builder模式
    Spring/Spring-Boot 学习 使用自定义的ArgumentResolver
    架构之分布式图片存储系统架构
    微服务和SOA服务
    Centos 上 Tengine安装
    .NET平台上插拔姿势的AOP
    P1424 刷题记录
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/4629335.html
Copyright © 2011-2022 走看看