草庐IT

C#实现FTP服务端和客户端

二次元攻城狮的博客 2023-03-28 原文

简介

FTP是FileTransferProtocol(文件传输协议)的英文简称,而中文简称为“文传协议”。用于Internet上的控制文件的双向传输。同时,它也是一个应用程序(Application)。基于不同的操作系统有不同的FTP应用程序,而所有这些应用程序都遵守同一种协议以传输文件。

FTP客户端

系统客户端

参考文章 文件资源管理器访问ftp服务器 ,在资源管理器输入框中输入 ftp://127.0.0.1/ ,如下所示:

客户端软件

WinSCP 是一个流行的 SFTP 客户端和 Microsoft Windows 的 FTP 客户端!使用在本地计算机和远程服务器之间复制文件FTP、FTPS、SCP、SFTP、WebDAV 或 S3 文件传输协议。
官网:https://winscp.net/eng/index.php
github:https://github.com/winscp/winscp
WinSCP也支持C#调用,参考 WinSCP .NET 程序集和 COM 库

自定义客户端

自定义客户端使用 FluentFTP 库,代码如下:

//创建FTP客户端并指定主机、用户名和密码(删除凭据以使用“匿名”帐户)
FtpClient client = new FtpClient("123.123.123.123", "david", "pass123");

//连接到服务器并自动检测工作FTP设置
client.AutoConnect();

//获取“/htdocs”文件夹中的文件和目录列表
foreach (FtpListItem item in client.GetListing("/htdocs"))
{
    //如果这是一个文件
    if (item.Type == FtpFileSystemObjectType.File)
    {
        //获取文件大小
        long size = client.GetFileSize(item.FullName);

        //计算服务器端文件的哈希值(默认算法)
        FtpHash hash = client.GetChecksum(item.FullName);
    }

    //获取文件或文件夹的修改日期/时间
    DateTime time = client.GetModifiedTime(item.FullName);

}

//上载文件
client.UploadFile(@"C:\MyVideo.mp4", "/htdocs/MyVideo.mp4");

//移动上载的文件
client.MoveFile("/htdocs/MyVideo.mp4", "/htdocs/MyVideo_2.mp4");

//再次下载文件
client.DownloadFile(@"C:\MyVideo_2.mp4", "/htdocs/MyVideo_2.mp4");

//将下载的文件与服务器进行比较
if (client.CompareFile(@"C:\MyVideo_2.mp4", "/htdocs/MyVideo_2.mp4") == FtpCompareResult.Equal) { }

//删除文件
client.DeleteFile("/htdocs/MyVideo_2.mp4");

//上载文件夹及其所有文件
client.UploadDirectory(@"C:\website\videos\", @"/public_html/videos", FtpFolderSyncMode.Update);

//上载文件夹及其所有文件,并删除服务器上的其他文件
client.UploadDirectory(@"C:\website\assets\", @"/public_html/assets", FtpFolderSyncMode.Mirror);

//下载文件夹及其所有文件
client.DownloadDirectory(@"C:\website\logs\", @"/public_html/logs", FtpFolderSyncMode.Update);

//下载文件夹及其所有文件,并删除磁盘上的其他文件
client.DownloadDirectory(@"C:\website\dailybackup\", @"/public_html/", FtpFolderSyncMode.Mirror);

//递归删除文件夹
client.DeleteDirectory("/htdocs/extras/");

//检查文件是否存在
if (client.FileExists("/htdocs/big2.txt")) { }

//检查文件夹是否存在
if (client.DirectoryExists("/htdocs/extras/")) { }

//上载文件并重试3次,然后放弃
client.RetryAttempts = 3;
client.UploadFile(@"C:\MyVideo.mp4", "/htdocs/big.txt", FtpRemoteExists.Overwrite, false, FtpVerify.Retry);

//断开再见!
client.Disconnect();

FTP服务端

系统服务端

参考 Win10--开启FTP的方法Windows10上怎样开启FTP服务

  • 启用FTP和IIS
  • 添加FTP站点
  • 设置身份验证
  • 设置防火墙

服务端软件

FTP服务端软件推荐使用Quick Easy FTP Server V4.0.0,界面如下:

自定义服务端

自定义服务器使用 FubarDev.FtpServer 库,代码如下

 // 设置依赖项注入
 var services = new ServiceCollection();

 // 使用%TEMP%/TestFtpServer作为根文件夹
 services.Configure<DotNetFileSystemOptions>(opt => opt
     .RootPath = Path.Combine(Path.GetTempPath(), "TestFtpServer"));

 // 添加FTP服务器服务
 // DotNetFileSystemProvider = 使用.NET文件系统功能
 // AnonymousMembershipProvider = 仅允许匿名登录
 services.AddFtpServer(builder => 
 {
     builder.UseDotNetFileSystem(); // 使用.NET文件系统功能
     builder.EnableAnonymousAuthentication();// 允许匿名登录
     /builder.Services.AddSingleton<IMembershipProvider, TestMembershipProvider>();//用户登录
 } ); 

 // 配置FTP服务器
 services.Configure<FtpServerOptions>(opt => opt.ServerAddress = "127.0.0.1");

 // 构建服务提供商
 using (var serviceProvider = services.BuildServiceProvider())
 {
     // 初始化FTP服务器
     var ftpServerHost = serviceProvider.GetRequiredService<IFtpServerHost>();

     // 启动FTP服务器
     ftpServerHost.StartAsync(CancellationToken.None).Wait();

     Console.WriteLine("Press ENTER/RETURN to close the test application.");
     Console.ReadLine();

     // 停止FTP服务器
     ftpServerHost.StopAsync(CancellationToken.None).Wait();
 }

需要先安装 Microsoft.Extensions.DependencyInjectionFubarDev.FtpServer.FileSystem.DotNet,完整的创建过程如下:

dotnet new console
dotnet add package FubarDev.FtpServer.FileSystem.DotNet
dotnet add package FubarDev.FtpServer
dotnet add package Microsoft.Extensions.DependencyInjection

官方的示例只有匿名登录,如果想使用用户校验,需要自己实现IMembershipProvider接口,代码如下:

public class TestMembershipProvider : IMembershipProvider
{
   
    public Task<MemberValidationResult> ValidateUserAsync(string username, string password)
    {
        if (username == "admin" && password == "admin")
        {
            var identity = new ClaimsIdentity();
            identity.AddClaim(new Claim(ClaimTypes.Name, username));
            identity.AddClaim(new Claim(ClaimTypes.Role, "admin"));
            return Task.FromResult(new MemberValidationResult(MemberValidationStatus.AuthenticatedUser, new ClaimsPrincipal(identity)));

        }

        return Task.FromResult(new MemberValidationResult(MemberValidationStatus.InvalidLogin));
     }
}

附件

有关C#实现FTP服务端和客户端的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  4. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  5. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  6. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  7. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  8. ruby-on-rails - 在 Rails 中调试生产服务器 - 2

    您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除

  9. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  10. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

随机推荐