C# 利用FluentFTP实现FTP上传下载功能

news2024/10/4 16:40:05

FTP作为日常工作学习中,非常重要的一个文件传输存储空间,想必大家都非常的熟悉了,那么如何快速的实现文件的上传下载功能呢,本文以一个简单的小例子,简述如何通过FluentFTP实现文件的上传和下载功能。仅供学习分享使用,如有不足之处,还请指正。

FTP基础知识

文件传输协议(File Transfer Protocol,FTP)是用于在网络上进行文件传输的一套标准协议,它工作在 OSI 模型的第七层, TCP 模型的第四层, 即应用层, 使用 TCP 传输而不是 UDP, 客户在和服务器建立连接前要经过一个“三次握手”的过程, 保证客户与服务器之间的连接是可靠的, 而且是面向连接, 为数据传输提供可靠保证。FTP允许用户以文件操作的方式(如文件的增、删、改、查、传送等)与另一主机相互通信。然而, 用户并不真正登录到自己想要存取的计算机上面而成为完全用户, 可用FTP程序访问远程资源, 实现用户往返传输文件、目录管理以及访问电子邮件等等, 即使双方计算机可能配有不同的操作系统和文件存储方式。

FTP环境搭建

在windows操作系统中,FTP可以通过(Internet Inforamtion Services, IIS)管理器进行创建,创建成功后即可进行查看,如下所示:

FluentFTP安装

FluentFTP是一款基于.Net的FTP和FTPS的客户端动态库,操作简单便捷。

首先创建基于.Net Framework 4.6.1的winform应用程序,然后通过Nuget包管理器进行安装,如下所示:

示例演示

 主要实现基于FTP的上传,下载,浏览等功能,如下所示:

 进入文件夹及右键下载,如下所示:

示例源码

FtpHelper类源码,封装了FTP文件的检索,上传,下载等功能,如下所示:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using FluentFTP;

namespace DemoFtp
{
    public class FtpHelper
    {
        #region 属性与构造函数

        /// <summary>
        /// IP地址
        /// </summary>
        public string IpAddr { get; set; }

        /// <summary>
        /// 相对路径
        /// </summary>
        public string RelatePath { get; set; }

        /// <summary>
        /// 端口号
        /// </summary>
        public int Port { get; set; }

        /// <summary>
        /// 用户名
        /// </summary>
        public string UserName { get; set; }

        /// <summary>
        /// 密码
        /// </summary>
        public string Password { get; set; }

        public FtpHelper()
        {

        }

        public FtpHelper(string ipAddr, int port, string userName, string password, string relatePath)
        {
            this.IpAddr = ipAddr;
            this.Port = port;
            this.UserName = userName;
            this.Password = password;
            this.RelatePath = relatePath;
        }

        #endregion

        #region 方法

        public FtpListItem[] ListDir() {
            FtpListItem[] lists;
            using (var ftpClient = new FtpClient(this.IpAddr, this.UserName, this.Password, this.Port))
            {
                ftpClient.Connect();
                ftpClient.SetWorkingDirectory(this.RelatePath);
                lists = ftpClient.GetListing();
            }
            return lists;
        }

        public void UpLoad(string dir, string file, out bool isOk)
        {
            isOk = false;
            FileInfo fi = new FileInfo(file);
            using (FileStream fs = fi.OpenRead())
            {
                //long length = fs.Length;
                using (var ftpClient = new FtpClient(this.IpAddr, this.UserName, this.Password, this.Port))
                {
                    ftpClient.Connect();
                    ftpClient.SetWorkingDirectory(this.RelatePath);
                    string remotePath = dir + "/" + Path.GetFileName(file);
                    var ftpRemodeExistsMode = file.EndsWith(".txt") ? FtpRemoteExists.Overwrite : FtpRemoteExists.Skip;
                    FtpStatus status = ftpClient.UploadStream(fs, remotePath, ftpRemodeExistsMode, true);
                    isOk = status == FtpStatus.Success;

                }
            }

        }

        /// <summary>
        /// 上传多个文件
        /// </summary>
        /// <param name="files"></param>
        /// <param name="isOk"></param>
        public void UpLoad(string dir, string[] files, out bool isOk)
        {
            isOk = false;
            if (CheckDirIsExists(dir))
            {
                foreach (var file in files)
                {
                    UpLoad(dir, file, out isOk);
                }
            }
        }


        private bool CheckDirIsExists(string dir)
        {
            bool flag = false;
            using (var ftpClient = new FtpClient(this.IpAddr, this.UserName, this.Password, this.Port))
            {
                ftpClient.Connect();
                ftpClient.SetWorkingDirectory(this.RelatePath);
                flag = ftpClient.DirectoryExists(dir);
                if (!flag)
                {
                    flag = ftpClient.CreateDirectory(dir);
                }
            }
            return flag;


        }

        /// <summary>
        /// 下载ftp
        /// </summary>
        /// <param name="localAddress"></param>
        /// <param name="remoteAddress"></param>
        /// <returns></returns>
        public bool DownloadFile(string localAddress, string remoteAddress)
        {
            using (var ftpClient = new FtpClient(this.IpAddr, this.UserName, this.Password, this.Port))
            {
                ftpClient.SetWorkingDirectory("/");
                ftpClient.Connect();
                if (ftpClient.DownloadFile(localAddress, remoteAddress) == FtpStatus.Success)
                {
                    return true;
                }
                return false;
            }
        }

        #endregion
    }
}

每一个FTP文件或文件夹,由一个自定义用户控件【PictureBox+Label+ContextMenu】表示,这样便于处理与显示:

using DemoFtp.Properties;
using FluentFTP;
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;

namespace DemoFtp
{
    public partial class FtpElementControl : UserControl
    {
        public Action<FtpListItem> SubFolderClick;

        public Action<FtpListItem> DownLoadClick;

        private FtpListItem ftpListItem;

        public FtpElementControl(FtpListItem ftpListItem)
        {
            InitializeComponent();
            this.ftpListItem = ftpListItem;
        }

        public FtpElementControl()
        {
            InitializeComponent();
        }

        public void InitControl()
        {
            if (ftpListItem.Type == FtpObjectType.Directory)
            {
                this.pbIcon.Image = Resources.folder.ToBitmap();
            }
            else if (ftpListItem.Type == FtpObjectType.File)
            {
                var name = ftpListItem.Name;
                var ext = Path.GetExtension(name).ToLower().Substring(1);
                if (ext == "png" || ext == "jpeg" || ext == "jpg" || ext == "bmp" || ext == "gif")
                {
                    this.pbIcon.Image = Resources.pictures.ToBitmap();
                }
                else if (ext == "doc" || ext == "docx")
                {
                    this.pbIcon.Image = Resources.doc.ToBitmap();
                }
                else if (ext == "exe")
                {
                    this.pbIcon.Image = Resources.setup.ToBitmap();
                }
                else
                {
                    this.pbIcon.Image = Resources.file;
                }
            }
            else
            {
                this.pbIcon.Image = Resources.file;
            }
            this.lblName.Text = ftpListItem.Name;
        }

        private void FtpElementControl_Load(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// 子菜单下载功能
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            this.DownLoadClick?.Invoke(ftpListItem);
        }

        /// <summary>
        /// 双击打开
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pbIcon_DoubleClick(object sender, EventArgs e)
        {
            this.SubFolderClick?.Invoke(ftpListItem);
        }
    }
}

主页面由一系列用户操作框和按钮组成,完成对FTP的基本操作,如下所示:

using FluentFTP;
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;

namespace DemoFtp
{
    public partial class MainForm : Form
    {
        private FtpHelper ftpHelper;

        public MainForm()
        {
            InitializeComponent();
        }

        private void btnLogin_Click(object sender, EventArgs e)
        {
            var url = txtFtpUrl.Text;
            var userName = txtUserName.Text;
            var password = txtPassword.Text;
            var port = txtPort.Text;
            if (this.lblRelatePath.Text != "/")
            {
                this.lblRelatePath.Text = "/";
            }
            var relatePath = this.lblRelatePath.Text;
            if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(port))
            {
                MessageBox.Show("路径和账号密码不可为空");
                return;
            }
            if (ftpHelper == null)
            {
                ftpHelper = new FtpHelper(url, int.Parse(port), userName, password, relatePath);

            }
            ListDir();
        }

        public void SubFolder(FtpListItem ftpListItem)
        {
            if (ftpListItem.Type == FtpObjectType.Directory)
            {
                var fullName = ftpListItem.FullName;
                ftpHelper.RelatePath = fullName;
                ListDir();
                this.lblRelatePath.Text = fullName;
            }
        }


        private void Download(FtpListItem ftpListItem) {
            var fullName=ftpListItem.FullName;
            var fileName = Path.GetFileName(fullName);
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.FileName = fileName;
            sfd.Title = "不载";
            sfd.Filter = "所有文档|*.*";
            if (DialogResult.OK == sfd.ShowDialog()) {
                ftpHelper.DownloadFile(sfd.FileName, fullName);
            }
        }

        private void ListDir()
        {
            this.ftpContainer.Controls.Clear();
            var ftpListItems = this.ftpHelper.ListDir();
            if (ftpListItems != null && ftpListItems.Length > 0)
            {
                foreach (var ftpListItem in ftpListItems)
                {
                    FtpElementControl ftpControl = new FtpElementControl(ftpListItem);
                    ftpControl.InitControl();
                    ftpControl.DownLoadClick += Download;
                    ftpControl.SubFolderClick += SubFolder;
                    this.ftpContainer.Controls.Add(ftpControl);
                }
            }
        }

        private void btnUpload_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "所有文件|*.*";
            ofd.Title = "请选择需要上传的文件";
            if (DialogResult.OK == ofd.ShowDialog()) {
                var localFile=ofd.FileName;
                ftpHelper.UpLoad(this.lblRelatePath.Text, localFile, out bool isOk);
                if (isOk) {
                    ListDir();
                }
            }
        }

        private void pbReturn_Click(object sender, EventArgs e)
        {
            var relativePath=this.lblRelatePath.Text;
            if (relativePath == "/") {
                return;
            }
            relativePath = relativePath.Substring(0, relativePath.LastIndexOf("/")+1);
            ftpHelper.RelatePath=relativePath;
            ListDir();
            this.lblRelatePath.Text = relativePath;
        }
    }
}

以上就是基于FluentFTP实现FTP上传下载的全部内容,旨在抛砖引玉,共同学习,一起进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/360521.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c++提高篇——queque容器

一、queque容器基本概念 Queue是一种先进先出(FIFO)的教据结构&#xff0c;它有两个出口 队列容器允许从一端新增元素&#xff0c;从另一端移除元素。队列中只有队头和队尾才可以被外界使用&#xff0c;因此队列不允许有遍历行为队列中进数据。 queque容器可以形象化为生活中…

第一个Java程序(初识Java)

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【JavaSE_primary】 文章目录1.Java概述1.1什么是Java1.2Java之父2.0第一个Java程序编译运行.class3.0程序如何跑起来的&#xff1f;3.1J…

39、基于51单片机声控光控灯人体感应路灯照明灯系统设计

摘 要 随着社会的不断进步&#xff0c;人们对低碳生活逐步认识和接受&#xff0c;并从很多方面开始关注&#xff0c;尤其是在环保上做出了很多努力。利用声音和光线的强弱来控制开关的断开或者闭合的电子产品来能够有效的降低能耗&#xff0c;节约能源。它不仅适用于住宅区的…

CMake构建静态库与动态库以及使用

CMake构建静态库与动态库一、任务二、准备工作三、编译共享库四、ADD_LIBRARY指令五、编译静态库5.1、SET_TARGET_PROPERTIES指令5.2、GET_TARGET_PROPERTY指令六、动态库版本号七、安装共享库和头文件八、使用外部共享库和头文件8.1、准备工作8.2、引入头文件搜索路径8.3、为 …

leetcode 11~20 学习经历

LeetCode 习题 11 - 2011. 盛最多水的容器12. 整数转罗马数字13. 罗马数字转整数14. 最长公共前缀15. 三数之和16. 最接近的三数之和17. 电话号码的字母组合18. 四数之和19. 删除链表的倒数第 N 个结点20. 有效的括号小结11. 盛最多水的容器 给定一个长度为 n 的整数数组 heigh…

【Servlet篇】Request请求转发详细解读

文章目录1. 前言2. 实战案例3. 特点1. 前言 请求转发是一种在服务器内部的资源跳转方式&#xff0c;如图&#xff1a; 上图的大致过程为&#xff0c;浏览器发送请求给服务器&#xff0c;服务器中 a 资源接收到请求&#xff0c;资源 a 处理完请求后将请求发送给资源 b&#xff…

cdr最新2023版本发布更新及CorelDraw功能介绍

CDR作为一款专业的平面设计软件&#xff0c;拥有着庞大的用户群体&#xff0c;而每年春天CorelDRAW新版本的发布也牵动着每一位小伙伴的心。CorelDraw2023近期刚刚发布本人就开始试用&#xff0c;感觉非常良好&#xff0c;特别给大家提出升级的N个理由!CorelDRAW2023最新版内置…

【基础算法】差分的应用(一维差分和二维差分)

&#x1f339;作者:云小逸 &#x1f4dd;个人主页:云小逸的主页 &#x1f4dd;Github:云小逸的Github &#x1f91f;motto:要敢于一个人默默的面对自己&#xff0c;强大自己才是核心。不要等到什么都没有了&#xff0c;才下定决心去做。种一颗树&#xff0c;最好的时间是十年前…

FPGA 20个例程篇:20.USB2.0/RS232/LAN控制并行DAC输出任意频率正弦波、梯形波、三角波、方波(一)

在最后一个例程中笔者精挑细选了一个较为综合性的项目实战&#xff0c;其中覆盖了很多知识点&#xff0c;也是从一个转产产品中所提炼出来的&#xff0c;所以非常贴近实战项目。 整个工程实现了用户通过对上位机PC端人机界面的操作&#xff0c;即可达到控制豌豆开发并行DAC输出…

Java---高级流

目录 一、转换流 &#xff08;1&#xff09;指定的字符集读写数据 二、序列化流和反序列化流 三、解压缩流和压缩流 &#xff08;1&#xff09;解压缩流 &#xff08;2&#xff09;压缩流 一&#xff1a;压缩文件 二&#xff1a;压缩文件夹 注&#xff1a;本文并未介绍J…

CVE-2023-24055 KeePass信息明文传输漏洞复现

前言 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任。 如果文章中的漏洞出现敏感内容产生了部分影响&#xff0c;请及时联系作者&#xff0c;望谅解。 一、漏洞描述 漏洞简述 Kee…

STM32 SystemInit()函数学习总结

拿到程序后如何看系统时钟&#xff1f;User文件夹——system_stm32f4xx程序&#xff0c;先找systemcoreclock(系统时钟&#xff09;但是这里这么多个系统时钟应该如何选择?点击魔法棒&#xff0c;然后点击C/C可以看到define的是F40_41XXX.USE这一款 &#xff0c;对应着就找出了…

R语言、MaxEnt模型融合技术的物种分布模拟、参数优化方法、结果分析制图与论文写作

基于R语言、MaxEnt模型融合技术的物种分布模拟、参数优化方法、结果分析制图与论文写作技术应用第一章、理论篇以问题导入的方式&#xff0c;深入掌握原理基础什么是MaxEnt模型&#xff1f;MaxEnt模型的原理是什么&#xff1f;有哪些用途&#xff1f;MaxEnt运行需要哪些输入文件…

对云原生集群网络流量可观测性的一点思考

问题背景 在云原生技术的广泛普及和实施过程中&#xff0c;笔者接触到的很多用户需求里都涉及到对云原生集群的可观测性要求。 实现集群的可观测性&#xff0c;是进行集群安全防护的前提条件 。而在可观测性的需求中&#xff0c;集群中容器和容器之间网络流量的可观测性需求是…

别错过!4C首发直播,上届全国总冠军带你入门赛题

和志同道合的伙伴并肩作战&#xff0c;用指尖敲出奇思妙想&#xff0c;飞桨黑客马拉松PaddlePadddle Hackathon第四期全新升级&#xff0c;开放报名啦&#xff01; 玩技术&#xff0c;秀操作&#xff01;这是一场高手云集的开发者盛会。四大赛道&#xff1a;核心框架开源贡献&…

Python每日一练(20230221)

目录 1. 不同路径 II 2. 字符串转换整数 (atoi) 3. 字符串相乘 1. 不同路径 II 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为“Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中…

一文讲明Hystrix熔断器

前言 解决问题: 主要防止服务器集群发生雪崩, 起到对服务器的保护作用 GitHub地址&#xff1a;https://github.com/Netflix/Hystrix/wiki 1 Hystrix是什么 1.1 分布式系统面临的问题 复杂分布式体系结构中的应用程序有数十个依赖关系&#xff0c;每个依赖关系在某些时候将不…

Milvus 群星闪耀时|又一个小目标达成 :社区正式突破 15,000 星!

如果把 Milvus 看作开源世界中的一束微光&#xff0c;那用户便是无垠宇宙中点点闪烁的星光。用户每一次点亮 star 之时&#xff0c;Milvus 就会迸发出更加耀眼的光芒。不知不觉&#xff0c;已有数以万计的 star 为 Milvus 而亮。2022 年 4 月&#xff0c;Milvus 在 GitHub 的 …

【C++】-- C++11基础常用知识点(下)

上篇&#xff1a; 【C】-- C11基础常用知识点&#xff08;上&#xff09;_川入的博客-CSDN博客 目录 新的类功能 默认成员函数 可变参数模板 可变参数 可变参数模板 empalce lambda表达式 C98中的一个例子 lambda表达式 lambda表达式语法 捕获列表 lambda表达底层 …

【Pytorch项目实战】基于PaddlenHub的口罩检测与语音提示

文章目录一、项目思路二、环境配置1.1、PaddlenHub模块&#xff08;飞桨预训练模型应用工具&#xff09;&#xff08;1&#xff09;预训练模型&#xff1a;pyramidbox_lite_mobile_mask&#xff08;2&#xff09;face_detection人脸检测模型&#xff08;默认为 pyramidbox_lite…