Demo_C#_Winform Ftp异步下载文件,更新ProgressBar

该博客介绍了如何在C# Winform应用中实现FTP异步下载文件,并同步更新ProgressBar的进度。作者通过创建一个FTP封装类,并结合多线程技术,确保在下载大文件如1.8G视频时能正确显示进度和完成状态。关键点包括遵循FTP文档编写类,使用事件更新进度,以及在多线程环境下安全地操作UI元素。
摘要由CSDN通过智能技术生成

由于研究Winform项目的版本自动检测更新,需要用到Ftp下载更新包文件。
特写出这个小Demo.
我的Ftp是本地用IIS搭建的FTP服务器,下载过一个1.8G的视频文件,亲测有效。
注意点:

  1. Ftp类编写需要参考FTP的帮助文档
  2. 同步更新下载进度状态、下载完成状态的方法:将更新事件的方法绑定到Ftp封装类公布的事件中。
  3. 多线程控制窗体控件的时候不能直接对控件进行赋值等操作,需要将操控UI的代码写在一个委托当中,然后用This.Invoke(操控控件委托)。

运行效果如图:
在这里插入图片描述
内容比较多,我会上传Demo附件

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Framework;

namespace DemoFtp
{
   
    public partial class Form1 : Form
    {
   
        public Form1()
        {
   
            InitializeComponent();
            txtLocalPath.Text = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
        }
        /// <summary>
        /// 主线程下载
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDownLoad_Click(object sender, EventArgs e)
        {
   
            FtpClient ftpClient = new FtpClient("192.168.0.104","/","FtpUser","Chendong144216,");
            string remoteFilePath = txtRemotePath.Text;
            string fileName = Path.GetFileName(remoteFilePath);
            string localFilePath = txtLocalPath.Text + "\\" + fileName;
            ftpClient.DownLoadFile(remoteFilePath, localFilePath);
        }
        /// <summary>
        /// 异步下载
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDownloadAsync_Click(object sender, EventArgs e)
        {
   
            FtpClient ftpClient = new FtpClient("192.168.0.104", "/", "FtpUser", "Chendong144216,");
            string remoteFilePath = txtRemotePath.Text;
            string fileName = Path.GetFileName(remoteFilePath);
            string localFilePath = txtLocalPath.Text + "\\" + fileName;
            ftpClient.DownloadProgressChanged += DownloadProgressChanged;
            ftpClient.DownloadDataCompleted += DownLoadDataComplete;
            Task<long> task = ftpClient.DownLoadFileAsync(remoteFilePath, txtLocalPath.Text, fileName);
        }
        /// <summary>
        /// 传入委托的方法,用于设置完成状态
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DownLoadDataComplete(object sender, FtpClient.UpDownLoadCompletedArgs e)
        {
   
            Action action = ()=> 
            {
   
                pgb.Value = 100;
                lblProgressValue.Text = "下载完毕";
            };
            this.Invoke(action);
        }
        /// <summary>
        /// 传入委托的方法,用于设置下载进度状态
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DownloadProgressChanged(object sender, FtpClient.UpDownLoadProcessArgs e)
        {
   
            Action<int> action = v =>
            {
   
                pgb.Value = v;
                lblProgressValue.Text = $"下载进度 {v}%";
            };
            this.Invoke(action, e.ProgressPercentage);
        }
    }
}

Ftp封装类

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Framework
{
   
    /// <summary>
    /// 文件结构信息
    /// </summary>
    public struct FtpFileStruct
    {
   
        /// <summary>
        /// 
        /// </summary>
        public string Flags;
        /// <summary>
        /// 拥有者
        /// </summary>
        public string Owner;
        /// <summary>
        /// 文件组
        /// </summary>
        public string Group;
        /// <summary>
        /// 是否目录
        /// </summary>
        public bool IsDirectory;
        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreateTime;
        /// <summary>
        /// 文件名
        /// </summary>
        public string Name;
        /// <summary>
        /// 文件长度
        /// </summary>
        public double Length;
    }
    /// <summary>
    /// 文件列表类型
    /// </summary>
    public enum FtpFileListStyle
    {
   
        UnixStyle,      //UNIX类型
        WindowsStyle,   //WINDOWS
        Unknown         //未知
    }
    /// <summary>
    /// 传输模式:二进制类型、ASCII类型
    /// </summary>
    public enum FtpTransferType {
    Binary, ASCII };
    /// <summary>
    /// Ftp上传下载
    /// </summary>
    public class FtpClient : IDisposable         //Ftp上传下载
    {
   
        #region Private Fields
        /// <summary>
        /// 用户名
        /// </summary>
        private string _UserName;
        /// <summary>
        /// 密码
        /// </summary>
        private string _Password;
        /// <summary>
        /// 初始创建Ftp类时候制定的根目录
        /// </summary>
        private string _RootDirectory;
        /// <summary>
        /// 工作目录
        /// </summary>
        private string _WorkDirectory;
        /// <summary>
        /// 服务器返回的应答信息(包含应答码)
        /// </summary>
        private string ReplyMessage {
    get; set; }
        /// <summary>
        /// 服务器返回的应答码
        /// </summary>
        private int ReplyCode {
    get; set; }
        /// <summary>
        /// 进行控制连接的socket
        /// </summary>
        private Socket _SocketControl;
        /// <summary>
        /// 传输模式
        /// </summary>
        private FtpTransferType _TransferType = Framework.FtpTransferType.ASCII;
        /// <summary>
        /// 接收和发送数据的缓冲区
        /// </summary>
        private Byte[] _Buffer = new Byte[BUFFER_SIZE];
        /// <summary>
        /// 当前尝试连接ID,用于报错
        /// </summary>
        IPAddress _IPAddress;
        int tryConnectTimes = 0;
        #endregion
        #region Property
        /// <summary>
        /// FTP服务器IP地址
        /// </summary>
        public string Host {
    get; set; }
        /// <summary>
        /// FTP服务器端口
        /// </summary>
        public int Port {
    get; set; }
        /// <summary>
        /// 目录
        /// </summary>
        public string WorkDirectory
        {
   
            get
            {
   
                if (!string.IsNullOrEmpty(_WorkDirectory)) return _WorkDirectory;
                if (!IsConnected) Connect();
                SetCurrentWorkDirectory();
                return _WorkDirectory;
            }
            set
            {
   
                if (string.IsNullOrEmpty(_RootDirectory))//第一次设置Directory的时候,定RootDirectory
                    _RootDirectory = value;
                if (_WorkDirectory != value)
                {
   
                    _WorkDirectory = value;
                    if (IsConnected)//如果正在连接,则更换当前目录
                        ChangeWorkDirectory(_WorkDirectory);
                }

            }
        }
        /// <summary>
        /// 在不知道当前路径的情况下提取并设置对应字段
        /// </summary>
        private void SetCurrentWorkDirectory()
        {
   
            SendCommand("PWD ");
            if (!(ReplyCode == 257)) throw new IOException(ReplyMessage.Substring(4));//return strPath;
            string dir = ReplyMessage.Substring(5);
            _WorkDirectory = dir.Substring(0, dir.IndexOf("\""));
        }

        /// <summary>
        /// 异步事件的间隔时间,毫秒
        /// </summary>
        public int AsyncTriggerInterval {
    get; set; } = 200;
        /// <summary>
        /// 缓冲大小
        /// </summary>
        public static int BUFFER_SIZE {
    get; set; } = 1024 * 8;
        /// <summary>
        /// 编码方式
        /// </summary>
        public Encoding Encoder {
    get; set; } = Encoding.Default;
        /// <summary>
        /// 代理
        /// </summary>
        public WebProxy WebProxy {
    get; }
        /// <summary>
        /// 是否登录
        /// </summary>
        public bool IsConnected {
    get; private set; }
        /// <summary>
        /// 获得传输模式
        /// </summary>
        /// <returns>传输模式</returns>
        public FtpTransferType TransferType
        {
   
            get {
    return _TransferType; }
            set 
            {
   
                if (value == _TransferType) return; //如果TransferType已经一样则不重复发送
                if (value == FtpTransferType.Binary)
                    SendCommand("TYPE I");//binary类型传输
                else
                    SendCommand("TYPE A");//ASCII类型传输
                if (ReplyCode != 200)
                    throw new IOException(ReplyMessage.Substring(4));
                else
                    _TransferType = value;
            }
        }
        #endregion
        #region EventArgs
        /// <summary>
        /// 上传下载进度
        /// </summary>
        public class UpDownLoadProcessArgs : EventArgs
        {
   
            private long _TotalBytes;
            private long _CurrentBytes;
            public UpDownLoadProcessArgs(long currentBytes, long totalBytes)
            {
   
                _CurrentBytes = currentBytes;
                _TotalBytes = totalBytes;
            }
            /// <summary>
            /// 完成进度百分比
            /// </summary>
            public int ProgressPercentage
            {
   
                get {
    return (int)(((double)_CurrentBytes / (double)_TotalBytes) * 100); }
            }
            /// <summary>
            /// 总字节数
            /// </summary>
            public long TotalBytes
            {
   
                get {
    return _TotalBytes; }
            }
            /// <summary>
            /// 当前字节数
            /// </summary>
            public long CurrentBytes
            {
   
                get {
    return _CurrentBytes; }
            }
        }
        /// <summary>
        /// 上传下载完成事件
        /// </summary>
        public class UpDownLoadCompletedArgs : EventArgs
        {
   
            private readonly long _TotalBytes;
            private readonly long _CurrentBytes;
            public UpDownLoadCompletedArgs(long curBytes, long totalBytes)
            {
   
                _CurrentBytes = curBytes;
                _TotalBytes = totalBytes;
            }
            /// <summary>
            /// 进度百分比
            /// </summary>
            public int ProgressPercentage
            {
   
                get {
    return (int)(((double)_CurrentBytes / (double)_TotalBytes) * 100); }
            }
            /// <summary>
            /// 是否完成
            /// </summary>
            public bool IsCompleted
            {
   
                get {
    return _CurrentBytes >= _TotalBytes; }
            }
            /// <summary>
            /// 总字节数
            /// </summary>
            public long TotalBytes
            {
   
                get {
    return _TotalBytes; }
            }
            /// <summary>
            /// 当前字节数
            /// </summary>
            public long CurrentBytes
            {
   
                get {
    return _CurrentBytes; }
            }
        }
        /// <summary>
        /// 返回服务器特性
        /// </summary>
        /// <returns></returns>
        public string Feature
        {
   
            get
            {
   
                SendCommand("FEAT");
                return ReplyMessage;
            }
        }
        #endregion
        #region Deletegate
        public delegate void FtpDownloadProgressChanged(object sender, UpDownLoadProcessArgs e);
        public delegate void FtpDownloadDataCompleted(object sender, UpDownLoadCompletedArgs e);
        public delegate void FtpUploadProgressChanged(object sender, UpDownLoadProcessArgs e);
        public delegate void FtpUploadFileCompleted(object sender, UpDownLoadCompletedArgs e);
        #endregion
        #region Event
        /// <summary>
        /// 异步下载进度发生改变触发的事件
        /// </summary>
        public event FtpDownloadProgressChanged DownloadProgressChanged;
        /// <summary>
        /// 异步下载文件完成之后触发的事件
        /// </summary>
        public event FtpDownloadDataCompleted DownloadDataCompleted;
        /// <summary>
        /// 异步上传进度发生改变触发的事件
        /// </summary>
        public event FtpUploadProgressChanged UploadProgressChanged;
        /// <summary>
        /// 异步上传文件完成之后触发的事件
        /// </summary>
        public</
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值