BirdMessenger 3.1.4

BirdMessenger
"Our aim is to solve the problem of unreliable file uploads once and for all. tus is a new open protocol for resumable uploads built on HTTP. It offers simple, cheap and reusable stacks for clients and servers. It supports any language, any platform and any network." - https://tus.io
BirdMessenger 中文名为:青鸟——相传为西王母的信使。 BirdMessnger 是一个基于.NET Standard 的 Tus协议的实现客户端。
Features
Protocol implementation
- Create
- HEAD
- PATCH
- OPTIONS
- DELETE
Install
Package manager
Install-Package BirdMessenger -Version 3.1.4
.NET CLI
dotnet add package BirdMessenger --version 3.1.4
Getting Started
public static Uri TusEndpoint = new Uri("http://localhost:5094/files");
static async Task Main(string[] args)
{
await DemoUseTusClientByDependencyInjection();
await DemoUseHttpClient();
}
/// <summary>
/// recommend using DependencyInjection
/// </summary>
private static async Task DemoUseTusClientByDependencyInjection()
{
var services = new ServiceCollection();
services.AddHttpClient<ITusClient, TusClient>(); // configure httpClient ,refer to https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
var serviceProvider = services.BuildServiceProvider();
var tusClient = serviceProvider.GetService<ITusClient>();
var location = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
// file to be uploaded
FileInfo fileInfo = new FileInfo(Path.Combine(location, @"TestFile/test.txt"));
using var fileStream = new FileStream(fileInfo.FullName,FileMode.Open,FileAccess.Read);
MetadataCollection metadata = new MetadataCollection();
metadata["filename"] = fileInfo.Name;
TusCreateRequestOption tusCreateRequestOption = new TusCreateRequestOption()
{
Endpoint = TusEndpoint,
Metadata = metadata,
UploadLength = fileStream.Length
};
var resp = await tusClient.TusCreateAsync(tusCreateRequestOption, CancellationToken.None);
TusPatchRequestOption tusPatchRequestOption = new TusPatchRequestOption
{
FileLocation = resp.FileLocation,
Stream = fileStream,
//UploadBufferSize = 2*1024*1024, // upload size ,default value is 1MB
//UploadType = UploadType.Chunk, // setting upload file with Stream or chunk ,default value is Stream
OnProgressAsync = x =>
{
var uploadedProgress = (int)Math.Floor(100 * (double)x.UploadedSize / x.TotalSize);
Console.WriteLine($"OnProgressAsync-TotalSize:{x.TotalSize}-UploadedSize:{x.UploadedSize}-uploadedProgress:{uploadedProgress}");
return Task.CompletedTask;
},
OnCompletedAsync = x =>
{
var reqOption = x.TusRequestOption as TusPatchRequestOption;
Console.WriteLine($"File:{reqOption.FileLocation} Completed ");
return Task.CompletedTask;
},
OnFailedAsync = x =>
{
Console.WriteLine($"error: {x.Exception.Message}");
if (x.OriginHttpRequestMessage is not null)
{
//log httpRequest
}
if (x.OriginResponseMessage is not null)
{
//log response
}
return Task.CompletedTask;
}
};
var tusPatchResp = await tusClient.TusPatchAsync(tusPatchRequestOption, CancellationToken.None);
}
/// <summary>
/// using httpclient directly
/// </summary>
private static async Task DemoUseHttpClient()
{
using var httpClient = new HttpClient();
var location = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
// file to be uploaded
FileInfo fileInfo = new FileInfo(Path.Combine(location, @"TestFile/test.txt"));
var fileStream = new FileStream(fileInfo.FullName,FileMode.Open,FileAccess.Read);
MetadataCollection metadata = new MetadataCollection();
metadata["filename"] = fileInfo.Name;
TusCreateRequestOption tusCreateRequestOption = new TusCreateRequestOption()
{
Endpoint = TusEndpoint,
Metadata = metadata,
UploadLength = fileStream.Length
};
var resp = await httpClient.TusCreateAsync(tusCreateRequestOption, CancellationToken.None);
bool isInvokeOnProgressAsync = false;
bool isInvokeOnCompletedAsync = false;
long uploadedSize = 0;
TusPatchRequestOption tusPatchRequestOption = new TusPatchRequestOption
{
FileLocation = resp.FileLocation,
Stream = fileStream,
//UploadBufferSize = 2*1024*1024, // upload size ,default value is 1MB
//UploadType = UploadType.Chunk, // setting upload file with Stream or chunk ,default value is Stream
OnProgressAsync = x =>
{
isInvokeOnProgressAsync = true;
uploadedSize = x.UploadedSize;
var uploadedProgress = (int)Math.Floor(100 * (double)x.UploadedSize / x.TotalSize);
Console.WriteLine($"OnProgressAsync-TotalSize:{x.TotalSize}-UploadedSize:{x.UploadedSize}-uploadedProgress:{uploadedProgress}");
return Task.CompletedTask;
},
OnCompletedAsync = x =>
{
isInvokeOnCompletedAsync = true;
var reqOption = x.TusRequestOption as TusPatchRequestOption;
Console.WriteLine($"File:{reqOption.FileLocation} Completed ");
return Task.CompletedTask;
},
OnFailedAsync = x =>
{
Console.WriteLine($"error: {x.Exception.Message}");
if (x.OriginHttpRequestMessage is not null)
{
//log httpRequest
}
if (x.OriginResponseMessage is not null)
{
//log response
}
return Task.CompletedTask;
}
};
var tusPatchResp = await httpClient.TusPatchAsync(tusPatchRequestOption, CancellationToken.None);
}
- You can see more examples in unit tests
Document
Development
Development is done on the 'master' branch.
Support and Sponsorship

Showing the top 20 packages that depend on BirdMessenger.
Packages | Downloads |
---|---|
Supabase.Storage
A C# implementation of the Supabase Storage client
|
2 |
.NET 5.0
- No dependencies.
.NET 6.0
- No dependencies.
.NET 7.0
- No dependencies.
.NET 8.0
- No dependencies.
.NET Standard 2.0
- No dependencies.
Version | Downloads | Last updated |
---|---|---|
3.1.4 | 2 | 10/08/2025 |
3.1.3 | 2 | 10/08/2025 |
3.1.2 | 2 | 10/08/2025 |
3.1.1 | 2 | 10/08/2025 |
3.1.0 | 3 | 10/08/2025 |
3.0.2 | 2 | 10/08/2025 |
3.0.1 | 2 | 10/08/2025 |
3.0.0 | 2 | 10/08/2025 |
3.0.0-beta1 | 2 | 10/08/2025 |
2.2.1 | 2 | 10/08/2025 |
2.2.0 | 2 | 10/08/2025 |
2.1.0-bata | 2 | 10/08/2025 |
2.0.1 | 2 | 10/08/2025 |
2.0.0 | 2 | 10/08/2025 |
1.0.1 | 2 | 10/08/2025 |
1.0.0 | 2 | 10/08/2025 |
1.0.0-beta1 | 2 | 10/08/2025 |
0.1.6 | 2 | 10/08/2025 |
0.1.5 | 2 | 10/08/2025 |
0.1.4 | 2 | 10/08/2025 |
0.1.3 | 2 | 10/08/2025 |
0.1.2 | 2 | 10/08/2025 |
0.1.1 | 2 | 10/08/2025 |
0.1.0 | 2 | 10/08/2025 |