Linger.FileSystem 0.4.0-alpha

This is a prerelease version of Linger.FileSystem.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package Linger.FileSystem --version 0.4.0-alpha
                    
NuGet\Install-Package Linger.FileSystem -Version 0.4.0-alpha
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Linger.FileSystem" Version="0.4.0-alpha" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Linger.FileSystem" Version="0.4.0-alpha" />
                    
Directory.Packages.props
<PackageReference Include="Linger.FileSystem" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Linger.FileSystem --version 0.4.0-alpha
                    
#r "nuget: Linger.FileSystem, 0.4.0-alpha"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#addin nuget:?package=Linger.FileSystem&version=0.4.0-alpha&prerelease
                    
Install Linger.FileSystem as a Cake Addin
#tool nuget:?package=Linger.FileSystem&version=0.4.0-alpha&prerelease
                    
Install Linger.FileSystem as a Cake Tool

Linger.FileSystem 文件系统库

概述

Linger.FileSystem 是一个统一的文件系统抽象库,提供了对多种文件系统的一致访问接口,包括本地文件系统、FTP和SFTP。通过这个库,您可以使用相同的API操作不同类型的文件系统,简化开发过程,提高代码复用性。

项目结构

Linger.FileSystem解决方案包含以下NuGet包:

  • Linger.FileSystem: 核心库,提供统一接口和本地文件系统实现
  • Linger.FileSystem.Ftp: FTP文件系统实现,基于FluentFTP
  • Linger.FileSystem.Sftp: SFTP文件系统实现,基于SSH.NET

安装方式

# 安装核心库
Install-Package Linger.FileSystem

# 安装FTP支持
Install-Package Linger.FileSystem.Ftp

# 安装SFTP支持
Install-Package Linger.FileSystem.Sftp

使用.NET CLI:

# 安装核心库
dotnet add package Linger.FileSystem

# 安装FTP支持
dotnet add package Linger.FileSystem.Ftp

# 安装SFTP支持
dotnet add package Linger.FileSystem.Sftp

架构设计

核心接口层次

IFileSystem                   IAsyncFileSystem
    │                              │
    └───────────────┬──────────────┘
                    │
          IFileSystemOperations
           /            \
ILocalFileSystem    IRemoteFileSystemContext

核心接口

  • IFileSystem: 定义基本同步文件操作接口
  • IAsyncFileSystem: 定义基本异步文件操作接口
  • IFileSystemOperations: 统一的文件系统操作接口,继承自上述两个接口
  • ILocalFileSystem: 本地文件系统特定接口,扩展了特有功能
  • IRemoteFileSystemContext: 远程文件系统连接管理接口

实现类层次

                FileSystemBase
                /           \
   LocalFileSystem     RemoteFileSystemBase
                         /         \
               FtpFileSystem    SftpFileSystem

基础类

  • FileSystemBase: 所有文件系统的抽象基类,实现了IFileSystemOperations接口
  • RemoteFileSystemBase: 远程文件系统的抽象基类,继承自FileSystemBase,实现了IRemoteFileSystemContext
  • LocalFileSystem: 本地文件系统具体实现
  • FtpFileSystem: FTP文件系统实现,基于FluentFTP库
  • SftpFileSystem: SFTP文件系统实现,基于SSH.NET库

设计模式

该库使用了以下设计模式:

  • 策略模式: 不同文件系统实现相同接口(IFileSystemOperations)但有各自的实现策略
  • 模板方法: 在FileSystemBase基类中定义算法骨架,子类实现具体步骤
  • 适配器模式: 将FluentFTP和SSH.NET等不同的文件系统API适配到统一接口
  • 简单工厂: 各个文件系统类内部的CreateClient()方法用于创建具体的客户端实例
  • 命令模式: 通过FileOperationResult封装操作结果,统一处理执行状态
  • 组合模式: 通过接口组合(IFileSystem和IAsyncFileSystem)构建更复杂的IFileSystemOperations
  • 代理模式: 远程文件系统的连接管理使用ConnectionScope作为代理,控制资源访问

关键流程

  1. 文件上传流程:

    • 客户端调用IFileSystemOperations.UploadAsync
    • 根据实际文件系统类型执行不同实现
    • 应用配置的文件命名规则和验证措施
    • 返回统一的FileOperationResult结果
  2. 远程系统连接管理:

    • 使用ConnectionScope确保连接的正确打开和关闭
    • 自动连接、操作、关闭的生命周期管理

主要特点

  • 统一接口: 通过 IFileSystemOperations 接口提供的一致API操作不同类型的文件系统
  • 支持多种文件系统: 包括本地文件系统、FTP和SFTP
  • 异步操作: 所有操作都支持异步方法,适用于现代应用程序开发
  • 自动重试: 内置重试机制,可以配置重试次数和延迟,提高操作可靠性
  • 连接管理: 自动处理远程文件系统的连接和断开
  • 多种命名规则: 支持MD5、UUID和普通命名规则

支持的.NET版本

  • .NET Framework 4.6.2+
  • .NET Standard 2.0+
  • .NET Core 2.0+/.NET 5+

安装

通过NuGet包管理器安装:

Install-Package Linger.FileSystem

或使用.NET CLI:

dotnet add package Linger.FileSystem

快速入门

使用本地文件系统

// 创建本地文件系统实例
var localFs = new LocalFileSystem("C:/Storage");

// 上传文件
using var fileStream = File.OpenRead("test.txt");
var result = await localFs.UploadAsync(fileStream, "uploads", "destination-file.txt", true);

// 检查上传结果
if (result.Success)
{
    Console.WriteLine($"文件上传成功: {result.FilePath}");
}

使用FTP文件系统

需要先安装Linger.FileSystem.Ftp包:

Install-Package Linger.FileSystem.Ftp

然后使用:

using Linger.FileSystem.Ftp;

// 创建FTP连接设置
var ftpSetting = new RemoteSystemSetting
{
    Host = "ftp.example.com",
    Port = 21,
    UserName = "username",
    Password = "password",
    Type = "FTP"
};

// 创建FTP文件系统实例
var ftpFs = new FtpFileSystem(ftpSetting);

// 上传文件
using var fileStream = File.OpenRead("test.txt");
var result = await ftpFs.UploadAsync(fileStream, "/public_html", "test.txt", true);

使用SFTP文件系统

需要先安装Linger.FileSystem.Sftp包:

Install-Package Linger.FileSystem.Sftp

然后使用:

using Linger.FileSystem.Sftp;

// 创建SFTP连接设置
var sftpSetting = new RemoteSystemSetting
{
    Host = "sftp.example.com",
    Port = 22,
    UserName = "username",
    Password = "password",
    Type = "SFTP"
};

// 创建SFTP文件系统实例
var sftpFs = new SftpFileSystem(sftpSetting);

// 上传文件
using var fileStream = File.OpenRead("test.txt");
var result = await ftpFs.UploadAsync(fileStream, "/home/user", "test.txt", true);

常见操作

文件上传

// 上传流
using var stream = File.OpenRead("local-file.txt");
var result = await fileSystem.UploadAsync(stream, "uploads", "destination-file.txt", true);

// 上传本地文件
result = await fileSystem.UploadFileAsync("local-file.txt", "uploads", true);

文件下载

// 下载到流
using var outputStream = new MemoryStream();
var result = await fileSystem.DownloadToStreamAsync("uploads/file.txt", outputStream);

// 下载到本地文件
result = await fileSystem.DownloadFileAsync("uploads/file.txt", "C:/Downloads/downloaded-file.txt", true);

文件删除

var result = await fileSystem.DeleteAsync("uploads/file-to-delete.txt");

目录操作

// 检查目录是否存在
bool exists = await fileSystem.DirectoryExistsAsync("uploads/images");

// 创建目录
await fileSystem.CreateDirectoryIfNotExistsAsync("uploads/documents");

配置选项

本地文件系统选项

var options = new LocalFileSystemOptions
{
    RootDirectoryPath = "C:/Storage",          // 根目录路径
    DefaultNamingRule = NamingRule.Md5,        // 默认命名规则: Md5、Uuid、Normal
    DefaultOverwrite = false,                  // 是否默认覆盖同名文件
    DefaultUseSequencedName = true,            // 文件名冲突时是否使用序号命名
    ValidateFileIntegrity = true,              // 是否验证文件完整性
    ValidateFileMetadata = false,              // 是否验证文件元数据
    CleanupOnValidationFailure = true,         // 验证失败时是否清理文件
    UploadBufferSize = 81920,                  // 上传缓冲区大小
    DownloadBufferSize = 81920,                // 下载缓冲区大小
    RetryOptions = new RetryOptions 
    { 
        MaxRetryCount = 3, 
        DelayMilliseconds = 1000 
    }
};

var localFs = new LocalFileSystem(options);

远程文件系统设置

var remoteSetting = new RemoteSystemSetting
{
    Host = "example.com",                      // 主机地址
    Port = 21,                                 // 端口 (FTP默认21,SFTP默认22)
    UserName = "username",                     // 用户名
    Password = "password",                     // 密码
    Type = "FTP",                              // 类型: "FTP" 或 "SFTP"
    ConnectionTimeout = 30000,                 // 连接超时(毫秒)
    OperationTimeout = 60000,                  // 操作超时(毫秒)
    // SFTP特定设置
    CertificatePath = "",                      // 证书路径
    CertificatePassphrase = ""                 // 证书口令
};

高级功能

FTP特有功能 (需要Linger.FileSystem.Ftp包)

using Linger.FileSystem.Ftp;

// 设置工作目录
await ftpFs.SetWorkingDirectoryAsync("/public_html");

// 列出目录
var files = await ftpFs.ListDirectoryAsync("/public_html");

// 批量上传文件
string[] localFiles = { "file1.txt", "file2.txt" };
var count = await ftpFs.UploadFilesAsync(localFiles, "/remote/path");

// 批量下载文件
string[] remoteFiles = { "/remote/file1.txt", "/remote/file2.txt" };
count = await ftpFs.DownloadFilesAsync("C:/Downloads", remoteFiles);

SFTP特有功能 (需要Linger.FileSystem.Sftp包)

using Linger.FileSystem.Sftp;

// 设置工作目录
sftpFs.SetWorkingDirectory("/home/user");

// 设置根目录为工作目录
sftpFs.SetRootAsWorkingDirectory();

// 列出目录中的文件
var files = await sftpFs.ListFilesAsync("/home/user");

// 列出目录中的子目录
var directories = await sftpFs.ListDirectoriesAsync("/home/user");

// 获取文件最后修改时间
var modTime = await sftpFs.GetLastModifiedTimeAsync("/home/user/file.txt");

本地文件系统高级功能

// 使用高级上传功能
var uploadedInfo = await localFs.UploadAsync(
    stream,
    "source-file.txt",  // 源文件名
    "container1",       // 容器名
    "images",           // 目标路径
    NamingRule.Md5,     // 命名规则
    false,              // 是否覆盖
    true                // 是否使用序号命名
);

// 访问上传后的信息
Console.WriteLine($"文件哈希: {uploadedInfo.HashData}");
Console.WriteLine($"相对路径: {uploadedInfo.FilePath}");
Console.WriteLine($"完整路径: {uploadedInfo.FullFilePath}");

连接管理

// 方式1: 使用using语句自动管理连接
using (var ftpFs = new FtpFileSystem(remoteSetting))
{
    // 操作自动处理连接和断开
    await ftpFs.UploadFileAsync("local.txt", "/remote/path");
}

// 方式2: 手动管理连接
try
{
    ftpFs.Connect();
    // 执行多个操作...
    await ftpFs.UploadFileAsync("file1.txt", "/remote");
    await ftpFs.UploadFileAsync("file2.txt", "/remote");
}
finally
{
    ftpFs.Disconnect();
}

异常处理

try
{
    var result = await ftpFs.UploadFileAsync("local.txt", "/remote");
    if (result.Success)
    {
        Console.WriteLine($"上传成功: {result.FilePath}");
    }
    else
    {
        Console.WriteLine($"上传失败: {result.ErrorMessage}");
    }
}
catch (FileSystemException ex)
{
    Console.WriteLine($"文件系统操作异常: {ex.Message}");
    Console.WriteLine($"操作: {ex.Operation}, 路径: {ex.Path}");
    if (ex.InnerException != null)
    {
        Console.WriteLine($"内部异常: {ex.InnerException.Message}");
    }
}

重试机制

var retryOptions = new RetryOptions
{
    MaxRetryCount = 5,                        // 最多重试5次
    DelayMilliseconds = 1000,                 // 初始延迟1秒
    MaxDelayMilliseconds = 30000,             // 最大延迟30秒
    UseExponentialBackoff = true              // 使用指数退避算法
};

// 为远程文件系统配置重试选项
var ftpFs = new FtpFileSystem(remoteSetting, retryOptions);

文件命名规则

本地文件系统支持三种文件命名规则:

  • Normal: 保持原始文件名
  • Md5: 使用文件内容的MD5哈希值命名
  • Uuid: 使用UUID生成唯一文件名
// 使用MD5命名规则
var result = await localFs.UploadAsync(
    fileStream, 
    "source.txt", 
    "container", 
    "uploads", 
    NamingRule.Md5
);

// 使用UUID命名规则
result = await localFs.UploadAsync(
    fileStream, 
    "source.txt", 
    "container", 
    "uploads", 
    NamingRule.Uuid
);

高级优化建议

缓冲区与内存管理

为提高大文件处理性能,可以考虑以下优化:

// 配置更高效的缓冲区大小
var options = new LocalFileSystemOptions
{
    RootDirectoryPath = "C:/Storage",          // 根目录路径
    DefaultNamingRule = NamingRule.Md5,        // 默认命名规则: Md5、Uuid、Normal
    DefaultOverwrite = false,                  // 是否默认覆盖同名文件
    DefaultUseSequencedName = true,            // 文件名冲突时是否使用序号命名
    ValidateFileIntegrity = true,              // 是否验证文件完整性
    ValidateFileMetadata = false,              // 是否验证文件元数据
    CleanupOnValidationFailure = true,         // 验证失败时是否清理文件
    UploadBufferSize = 262144,                 // 增加到256KB以提升大文件上传性能
    DownloadBufferSize = 262144,               // 增加到256KB以提升大文件下载性能
    RetryOptions = new RetryOptions 
    { 
        MaxRetryCount = 3, 
        DelayMilliseconds = 1000 
    }
};

批量操作优化

对于需要处理大量文件的场景,可以使用批处理API减少连接开销:

// FTP系统批量操作示例 - 比单个操作更高效
string[] localFiles = Directory.GetFiles("local/directory", "*.txt");
await ftpFs.UploadFilesAsync(localFiles, "/remote/path");

贡献

欢迎提交Pull Request和Issue帮助我们改进这个库。

许可证

MIT

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Linger.FileSystem:

Package Downloads
Linger.FileSystem.Sftp

Package Description

Linger.FileSystem.Ftp

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.5.0-alpha 123 4/10/2025
0.4.0-alpha 116 4/1/2025
0.3.3-alpha 120 3/19/2025
0.3.2-alpha 114 3/17/2025
0.3.1-alpha 103 3/16/2025
0.3.0-alpha 186 3/6/2025
0.2.0-alpha 67 2/9/2025
0.1.2-alpha 64 12/17/2024
0.1.1-alpha 62 12/17/2024
0.1.0-alpha 71 12/6/2024
0.0.4-alpha 59 12/6/2024
0.0.3-alpha 84 8/9/2024
0.0.2-alpha 76 8/9/2024
0.0.1-alpha 60 8/7/2024