C# FTP服务器 FTP客户端,文件上传下载
主要使用的软件是 HslCommunication 关于这个软件的本身,详细可以参考下面的地址:
github地址:https://github.com/dathlin/HslCommunication
官网:http://www.hsltechnology.cn
加群咨询学习信息:http://www.hslcommunication.cn/Cooperation
在Visual Studio 中的NuGet管理器中可以下载安装,也可以直接在NuGet控制台输入下面的指令安装:
Install-Package HslCommunication
如果需要教程:Nuget安装教程:http://www.cnblogs.com/dathlin/p/7705014.html
组件的api地址:http://api.hslcommunication.cn
使用手册:http://www.hsltechnology.cn/Doc/HslCommunication
Demo下载地址:http://www.hsltechnology.cn/Home/Download
在开始之前,我们先来看看HslCommunication能干什么?

1. Demo快速体验
如果我们想快速搭建一个 FTP服务器, 然后在客户端进行收发文件操作的话,使用我们得 Demo程序 是非常快,并且简单的。我们先打开Demo得服务器

然后我们在打开一个客户端,输入ip地址及端口号,然后点击 连接, 刷新 操作,我们可以看到,服务器的文件目录显示出来了

然后在树形目录里选择右键菜单操作,可以下载,删除,重命名文件

当然针对文件夹右键操作,有删除,重命名,批量下载,批量上传操作

如果我们的 FTP服务器 运行在云服务器的话,相关端口的权限得放行,不然无法通信的,除了主服务器端口之外,还有一个用于上传,下载,获取文件列表时使用的临时端口, 这个临时端口是随机的,不过我们可以在 Demo 程序里指定。

引用库
using HslCommunication; using HslCommunication.Core; using HslCommunication.Enthernet.Ftp;
服务器代码实现
服务器端写代码是非常容易的,下面的代码使用了更多的功能,所以稍微复杂一点,实际情况可以自己裁减
class Program
{
static void Main( string[] args )
{
HslCommunication.Enthernet.Ftp.FtpServer ftpServer = new HslCommunication.Enthernet.Ftp.FtpServer( );
ftpServer.CurrentDirectory = @"E:\Software\HslCommunicationDemo\"; // 遍历的路径
ftpServer.AllowAnonymous = true; // 允许匿名用户登录
ftpServer.DownloadOnly = false; // 如果只允许遍历和下载,设置为true,安全性高
// ftpServer.SetPasvPortRange( "7000-8000" ); // 如果要设置随机的端口范围
// 自定义的账户检查,如果不绑定该事件,就是只使用匿名登录
ftpServer.CheckAccountFunction = new Func<string, string, HslCommunication.Enthernet.Ftp.FtpSession, OperateResult>( ( name, pwd, session ) =>
{
// session.CanEdit = false; // 如果要控制某个会话没有上传和删除的权限,设置会话的该属性
if (name == "admin" && pwd == "123456") return OperateResult.CreateSuccessResult( );
return new OperateResult( 500, "user account or password wrong" ); // 不允许登录返回的信息
} );
try
{
ftpServer.ServerStart( Convert.ToInt32( "12345" ) );
}
catch (Exception ex)
{
Console.WriteLine( "Server Start failed: " + ex.ToString( ) );
}
Console.ReadLine( );
}
}
客户端代码实现
实例化操作
HslCommunication.Enthernet.Ftp.FtpClient ftpClient = new HslCommunication.Enthernet.Ftp.FtpClient( );
ftpClient.IpAddress = "127.0.0.1";
ftpClient.Port = 12345;
//ftpClient.Username = "admin"; // 匿名的话,用户名密码,不用输入
//ftpClient.Password = "12345";
遍历指定目录的文件夹名称及文件列表
Console.WriteLine( "List files..." );
OperateResult<HslCommunication.Enthernet.Ftp.FtpFileItem[]> list = ftpClient.ListFiles( "/" ); // 如果其它目录就是 /Files/
if (list.IsSuccess)
{
for (int i = 0; i < list.Content.Length; i++)
{
HslCommunication.Enthernet.Ftp.FtpFileItem ftpFileItem = list.Content[i];
if (ftpFileItem.IsDirectory)
{
Console.WriteLine( "Path: " + ftpFileItem.Name );
}
else
{
Console.WriteLine( "File: " + ftpFileItem.Name + " Size: " + ftpFileItem.Size + " Time: " + ftpFileItem.CreateTime );
}
}
}
下载一个文件
// 第一个参数是FTP文件服务器的路径,第二个参数是本地存储的路径
OperateResult result = ftpClient.DownloadFile( "FtpFiles/secs_f.png", @"E:\Software\HslCommunicationDemo\FtpFiles\secs_f.png" );
if (result.IsSuccess)
{
Console.WriteLine( "文件下载成功" );
}
else
{
Console.WriteLine( "文件下载失败: " + result.Message );
}
如果想要支持进度报告的话,代码如下
static void Main( string[] args )
{
HslCommunication.Enthernet.Ftp.FtpClient ftpClient = new HslCommunication.Enthernet.Ftp.FtpClient( );
ftpClient.IpAddress = "127.0.0.1";
ftpClient.Port = 12345;
//ftpClient.Username = "admin"; // 匿名的话,用户名密码,不用输入
//ftpClient.Password = "12345";
Console.WriteLine( "download file..." );
// 第一个参数是FTP文件服务器的路径,第二个参数是本地存储的路径
OperateResult result = ftpClient.DownloadFile( "FtpFiles/secs_f.png", @"E:\Software\HslCommunicationDemo\FtpFiles\secs_f.png", ReportDownloadProgress
);
if (result.IsSuccess)
{
Console.WriteLine( "文件下载成功" );
}
else
{
Console.WriteLine( "文件下载失败: " + result.Message );
}
Console.ReadLine( );
}
// 这里方法传入下载的参数,已下载字节数,总字节数
private static void ReportDownloadProgress( long already, long total )
{
Console.WriteLine( "Already Bytes: " + already + " Total: " + total + " Percent: " + (already * 100 / total) + "%" );
}
上传一个文件
// 第一个参数是本地文件路径,第二个参数是FTP服务器存储的路径
OperateResult result = ftpClient.UploadFile( @"E:\Software\HslRedisDesktop\yudian.png", "/yudian.png" );
if (result.IsSuccess)
{
Console.WriteLine( "文件上传成功" );
}
else
{
Console.WriteLine( "文件上传失败: " + result.Message );
}
上传文件的功能也是支持进度报告的,这里尝试另一个写法,使用匿名委托 + Lamda表达式实现
// 第一个参数是本地文件路径,第二个参数是FTP服务器存储的路径
OperateResult result = ftpClient.UploadFile( @"E:\Software\HslRedisDesktop\yudian.png", "/yudian.png",
new Action<long, long>( ( already, total ) =>
{
Console.WriteLine( "Already Bytes: " + already + " Total: " + total + " Percent: " + (already * 100 / total) + "%" );
} ) );
if (result.IsSuccess)
{
Console.WriteLine( "文件上传成功" );
}
else
{
Console.WriteLine( "文件上传失败: " + result.Message );
}
删除一个文件
// 参数是原FTP服务器存储的路径, 新的文件名,前者需要带路径
OperateResult result = ftpClient.RenameFile( "/secs_f.png", "secs_f2.png" );
if (result.IsSuccess)
{
Console.WriteLine( "重命名文件成功" );
}
else
{
Console.WriteLine( "重命名文件失败: " + result.Message );
}
重命名文件夹
// 旧的路径和新的路径 例如 /A/testC testD
OperateResult result = ftpClient.RenameFolder( "testC", "testA" );
if (result.IsSuccess)
{
Console.WriteLine( "重命名目录成功" );
}
else
{
Console.WriteLine( "重命名目录失败: " + result.Message );
}
删除路径
OperateResult result = ftpClient.DeleteDirectory( "testA/AA/" );
if (result.IsSuccess)
{
Console.WriteLine( "目录删除成功" );
}
else
{
Console.WriteLine( "目录删除失败: " + result.Message );
}
一个winform的复杂例子,后台线程下载,更新进度,带取消按钮
private HslCancelToken downloadCacel = null; // 取消令牌很关键
private void DownloadFileExample( )
{
button_download.Enabled = false; // 下载按钮禁止,打开取消下载按钮
button_download_cancel.Enabled = true;
label15.Text = "Start downloading...";
downloadCacel = new HslCancelToken( ); // 取消令牌实例化
ThreadPool.QueueUserWorkItem( new WaitCallback( ThreadPoolDownloadFile ), "/secs_f2.png" );
}
// 点击下载取消的按钮,取消的令牌设置为 True
private void button_download_cancel_Click( object sender, EventArgs e )
{
if (downloadCacel != null) downloadCacel.IsCancelled = true;
}
private void ThreadPoolDownloadFile( object state )
{
string fileName = state as string;
DateTime downloadStartTime = DateTime.Now;
OperateResult result = ftpClient.DownloadFile(
fileName, // 文件在服务器上保存的名称,举例123.txt
"D:\\secs_f2.png", // 下载后在文本保存的路径,也可以直接下载到 MemoryStream 的数据流中, 或是手动选择存储路径
DownloadReportProgress, // 文件下载的时候的进度报告,友好的提示下载进度信息
downloadCacel // 下载取消的令牌
);
// 切换窗体线程显示
Invoke( new Action( ( ) =>
{
button_download.Enabled = true;
button_download_cancel.Enabled = false;
if (result.IsSuccess)
{
// message: file download success
label15.Text = "文件下载成功!耗时:" + (DateTime.Now - downloadStartTime).TotalSeconds.ToString( "F1" ) + " 秒";
}
else
{
// 失败原因多半来自网络异常,还有文件不存在,分类名称填写异常
// mostly failed by network exception, like offline, and file not exsist,
label15.Text = "文件下载失败:" + result.Message;
MessageBox.Show( "文件下载失败:" + result.ToMessageShowString( ) );
}
} ) );
}
/// <summary>
/// 用于更新文件下载进度的方法,该方法是线程安全的,主要作用是将下载文件的进度在进度条上显示
/// </summary>
/// <param name="receive">已经接收的字节数</param>
/// <param name="totle">总字节数</param>
private void DownloadReportProgress( long receive, long totle )
{
if (progressBar2.InvokeRequired)
{
progressBar2.Invoke( new Action<long, long>( DownloadReportProgress ), receive, totle );
return;
}
// 此处代码是线程安全的
// thread-safe code
int value = (int)(receive * 100L / totle);
progressBar2.Value = value;
label9.Text = SoftBasic.GetSizeDescription( receive ) + "/" + SoftBasic.GetSizeDescription( totle ); // 已下载/总大小
}

浙公网安备 33010602011771号