FastDFS.Client
1.0.0
dotnet add package FastDFS.Client --version 1.0.0
NuGet\Install-Package FastDFS.Client -Version 1.0.0
<PackageReference Include="FastDFS.Client" Version="1.0.0" />
<PackageVersion Include="FastDFS.Client" Version="1.0.0" />
<PackageReference Include="FastDFS.Client" />
paket add FastDFS.Client --version 1.0.0
#r "nuget: FastDFS.Client, 1.0.0"
#:package FastDFS.Client@1.0.0
#addin nuget:?package=FastDFS.Client&version=1.0.0
#tool nuget:?package=FastDFS.Client&version=1.0.0
FastDFS.Client
A modern, high-performance FastDFS .NET client library with built-in connection pooling and multi-cluster support.
Features
- ✅ High Performance: Uses modern Socket API instead of TcpClient for better throughput and lower latency
- ✅ Target Framework: netstandard2.0 (compatible with .NET Framework 4.6.1+, .NET Core 2.0+, .NET 5+)
- ✅ Connection Pooling: Automatic connection management with configurable pool sizes
- ✅ Multi-Cluster Support: Manage multiple FastDFS clusters with named clients
- ✅ Full Async/Await: All operations are fully asynchronous
- ✅ Dependency Injection: First-class DI support with IOptions pattern
- ✅ Non-DI Support: Factory pattern for non-DI scenarios
- ✅ Logging Integration: Built-in logging with
Microsoft.Extensions.Logging - ✅ Automatic Failover: Tracker server failover support
- ✅ Zero Dependencies: Core library has no external dependencies
- ✅ Comprehensive Tests: 86+ unit tests with 100% pass rate
Quick Start
Installation
dotnet add package FastDFS.Client
Basic Usage (Dependency Injection)
Single Cluster:
// Startup.cs or Program.cs
services.AddFastDFS(options =>
{
options.TrackerServers = new[] { "192.168.1.100:22122" };
options.ConnectionPool = new ConnectionPoolConfiguration
{
MaxConnectionPerServer = 50,
MinConnectionPerServer = 5
};
});
// Usage in your service
public class FileService
{
private readonly IFastDFSClient _client;
public FileService(IFastDFSClient client)
{
_client = client;
}
public async Task<string> UploadFile(byte[] content, string extension)
{
// Upload returns file ID like: group1/M00/00/00/wKgBaGVlYWRlYS5qcGc
return await _client.UploadAsync(null, content, extension);
}
}
Multiple Clusters:
// Register multiple clusters
services.AddFastDFS("default", options =>
{
options.TrackerServers = new[] { "192.168.1.100:22122" };
});
services.AddFastDFS("backup", options =>
{
options.TrackerServers = new[] { "192.168.2.100:22122" };
});
// Usage
public class FileService
{
private readonly IFastDFSClient _defaultClient;
private readonly IFastDFSClient _backupClient;
public FileService(IFastDFSClientFactory factory)
{
_defaultClient = factory.GetClient("default");
_backupClient = factory.GetClient("backup");
}
}
Configuration (appsettings.json)
{
"FastDFS": {
"Clusters": {
"default": {
"TrackerServers": ["192.168.1.100:22122", "192.168.1.101:22122"],
"ConnectionPool": {
"MaxConnectionPerServer": 50,
"MinConnectionPerServer": 5,
"ConnectionIdleTimeout": 300,
"ConnectionLifetime": 3600
},
"NetworkTimeout": 30,
"Charset": "UTF-8"
},
"backup": {
"TrackerServers": ["192.168.2.100:22122"],
"ConnectionPool": {
"MaxConnectionPerServer": 30,
"MinConnectionPerServer": 3
}
}
}
}
}
services.AddFastDFS(configuration.GetSection("FastDFS"));
Non-DI Usage
var options = new FastDFSConfiguration
{
TrackerServers = new[] { "192.168.1.100:22122" }
};
var client = FastDFSClientBuilder.CreateClient(options);
// Upload file
var fileId = await client.UploadAsync(fileBytes, ".jpg");
// Download file
var content = await client.DownloadAsync(fileId);
// Delete file
await client.DeleteAsync(fileId);
API Overview
Upload Operations
// Upload from byte array (auto-select group)
string fileId = await client.UploadAsync(null, bytes, "jpg");
// Returns: "group1/M00/00/00/wKgBaGVlYWRlYS5qcGc"
// Upload to specific group
string fileId = await client.UploadAsync("group1", bytes, "jpg");
// Upload from stream
string fileId = await client.UploadAsync(null, stream, "pdf");
// Upload from file path
string fileId = await client.UploadFileAsync(null, "/path/to/file.png");
// Upload appender file (supports append later)
string fileId = await client.UploadAppenderFileAsync(null, bytes, "log");
// Append to appender file
await client.AppendFileAsync(fileId, newBytes);
Download Operations
// Download to byte array
byte[] content = await client.DownloadAsync(fileId);
// Download to stream
await client.DownloadAsync(fileId, outputStream);
// Download to file
await client.DownloadFileAsync(fileId, "/save/path.jpg");
// Partial download (offset and length)
byte[] partial = await client.DownloadAsync(fileId, offset: 1024, length: 2048);
File Management
// Query file info
FastDFSFileInfo info = await client.QueryFileInfoAsync(fileId);
Console.WriteLine($"Size: {info.FileSize}, CRC32: {info.Crc32}");
// Check if file exists
bool exists = await client.FileExistsAsync(fileId);
// Delete file
await client.DeleteAsync(fileId);
// Set metadata
var metadata = new FastDFSMetadata
{
{ "author", "John" },
{ "created", "2024-01-01" },
{ "width", "1920" },
{ "height", "1080" }
};
await client.SetMetadataAsync(fileId, metadata, MetadataFlag.Overwrite);
// Get metadata
FastDFSMetadata metadata = await client.GetMetadataAsync(fileId);
string author = metadata["author"];
Advanced Usage
Connection Pool Configuration
services.AddFastDFS(options =>
{
options.TrackerServers = new[] { "192.168.1.100:22122", "192.168.1.101:22122" };
options.ConnectionPool = new ConnectionPoolConfiguration
{
MaxConnectionPerServer = 50, // Maximum connections per server
MinConnectionPerServer = 5, // Minimum connections (pre-warmed)
ConnectionIdleTimeout = 300, // Idle timeout in seconds
ConnectionLifetime = 3600, // Max lifetime in seconds
ConnectionTimeout = 30000, // Connection timeout in ms
SendTimeout = 30000, // Send timeout in ms
ReceiveTimeout = 30000 // Receive timeout in ms
};
options.Charset = "UTF-8";
options.NetworkTimeout = 30;
});
Storage Server Selection Strategy
services.AddFastDFS(options =>
{
options.TrackerServers = new[] { "192.168.1.100:22122" };
// Choose storage selection strategy:
options.StorageSelectionStrategy = StorageSelectionStrategy.TrackerSelection; // Default, let tracker decide
// options.StorageSelectionStrategy = StorageSelectionStrategy.RoundRobin;
// options.StorageSelectionStrategy = StorageSelectionStrategy.Random;
// options.StorageSelectionStrategy = StorageSelectionStrategy.FirstAvailable;
});
HTTP URL Generation (for FastDFS Nginx Module)
FastDFS supports HTTP access through the fastdfs-nginx-module. This SDK can generate HTTP URLs for files:
services.AddFastDFS(options =>
{
options.TrackerServers = new[] { "192.168.1.100:22122" };
// Configure HTTP access
options.HttpConfig = new HttpConfiguration
{
// Option 1: Configure HTTP server URLs for each group
ServerUrls = new Dictionary<string, string>
{
{ "group1", "http://img1.example.com" },
{ "group2", "http://img2.example.com" }
},
// Option 2: Use template with storage server IP (if not using separate HTTP domain)
// DefaultServerUrlTemplate = "http://{ip}:8080", // {ip} will be replaced with storage IP
// Anti-steal token configuration (optional, requires Nginx module setup)
AntiStealTokenEnabled = true,
SecretKey = "your-secret-key-here", // Must match Nginx configuration
DefaultTokenExpireSeconds = 3600 // Token valid for 1 hour
};
});
Generate HTTP URLs:
// Simple HTTP URL
string url = await client.GetFileUrlAsync(fileId);
// Result: http://img1.example.com/group1/M00/00/00/xxxxx.jpg
// HTTP URL with custom download filename
string url = await client.GetFileUrlAsync(fileId, attachmentFilename: "my-photo.jpg");
// Result: http://img1.example.com/group1/M00/00/00/xxxxx.jpg?attname=my-photo.jpg
// Secure URL with anti-steal token (1 hour expiration)
string secureUrl = await client.GetFileUrlWithTokenAsync(fileId, expireSeconds: 3600);
// Result: http://img1.example.com/group1/M00/00/00/xxxxx.jpg?token=abc123&ts=1234567890
// Secure URL with custom filename
string secureUrl = await client.GetFileUrlWithTokenAsync(fileId, expireSeconds: 3600, attachmentFilename: "photo.jpg");
// Result: http://img1.example.com/group1/M00/00/00/xxxxx.jpg?token=abc123&ts=1234567890&attname=photo.jpg
Usage scenarios:
- Generate URLs for browser direct access
- Integrate with CDN for faster delivery
- Secure file access with time-limited tokens
- Custom download filenames for better user experience
Logging Integration
services.AddLogging(builder =>
{
builder.AddConsole();
builder.SetMinimumLevel(LogLevel.Debug);
});
services.AddFastDFS(options =>
{
options.TrackerServers = new[] { "192.168.1.100:22122" };
});
// Logs will automatically include:
// - Connection pool events (creation, reuse, disposal)
// - Tracker failover events
// - Upload/download operations
// - Network errors
Error Handling
try
{
var fileId = await client.UploadAsync(null, bytes, "jpg");
}
catch (FastDFSNetworkException ex)
{
// Network-related errors (connection failed, timeout, etc.)
_logger.LogError(ex, "Network error: {Endpoint}", ex.RemoteEndpoint);
}
catch (FastDFSProtocolException ex)
{
// Protocol errors (invalid response, server error, etc.)
_logger.LogError(ex, "Protocol error: {ErrorCode}", ex.ErrorCode);
}
catch (FastDFSException ex)
{
// General FastDFS errors
_logger.LogError(ex, "FastDFS error: {Message}", ex.Message);
}
Multi-Cluster Failover Example
public class RobustFileService
{
private readonly IFastDFSClient _primaryClient;
private readonly IFastDFSClient _backupClient;
private readonly ILogger<RobustFileService> _logger;
public RobustFileService(IFastDFSClientFactory factory, ILogger<RobustFileService> logger)
{
_primaryClient = factory.GetClient("primary");
_backupClient = factory.GetClient("backup");
_logger = logger;
}
public async Task<string> UploadWithFailover(byte[] content, string extension)
{
try
{
return await _primaryClient.UploadAsync(null, content, extension);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Primary cluster failed, using backup");
return await _backupClient.UploadAsync(null, content, extension);
}
}
}
Performance Tips
- Use Connection Pooling: Always use the built-in connection pool instead of creating new clients for each operation
- Reuse Clients: IFastDFSClient instances are thread-safe and should be reused
- Adjust Pool Size: Tune
MaxConnectionPerServerbased on your workload - Enable Logging: Use logging to monitor connection pool efficiency
- Use Async Operations: All operations are async - use
awaitproperly to avoid blocking threads
Building
# Restore dependencies
dotnet restore
# Build
dotnet build
# Run tests
dotnet test
# Pack NuGet package
dotnet pack -c Release
Project Structure
FastDFS.Client/
├── src/
│ ├── FastDFS.Client/ # Core library (zero dependencies)
│ │ ├── Protocol/ # FastDFS protocol implementation
│ │ ├── Connection/ # Socket connection and pooling
│ │ ├── Tracker/ # Tracker client
│ │ ├── Storage/ # Storage client
│ │ ├── Configuration/ # Configuration models
│ │ ├── Exceptions/ # Custom exceptions
│ │ └── Utilities/ # Helper utilities
│ └── FastDFS.Client.DependencyInjection/ # DI extensions
├── tests/
│ └── FastDFS.Client.Tests/ # Unit tests (86+ tests)
└── samples/
└── FastDFS.Client.Samples/ # Usage examples
Architecture
See CLAUDE.md for detailed architecture documentation and development guidelines.
Requirements
- FastDFS Server 6.0+ (recommended)
- .NET Standard 2.0 compatible runtime
- .NET Framework 4.6.1+
- .NET Core 2.0+
- .NET 5.0+
- .NET 6.0+
- .NET 7.0+
- .NET 8.0+
License
MIT License - see LICENSE file for details
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Support
| Product | Versions 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 was computed. 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 was computed. 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. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.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. |
-
.NETStandard 2.0
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.0)
- System.Buffers (>= 4.6.1)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on FastDFS.Client:
| Package | Downloads |
|---|---|
|
FastDFS.Client.DependencyInjection
Dependency injection extensions for FastDFS.Client with IOptions pattern and multi-cluster support |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 493 | 12/9/2025 |
Initial release with core functionality:
- FastDFS protocol implementation
- Connection pooling with lifecycle management
- Tracker and Storage client
- Multi-cluster support
- Dependency injection integration
- High-performance Socket-based networking