tusdotnet: a .NET server for resumable file uploads
.NET server implementation of the Tus protocol for resumable file uploads. Read more at https://tus.io
At a glance
- What is it?
- tusdotnet is a server implementation of the Tus protocol for resumable uploads, hosted with OWIN or ASP.NET Core on .NET Framework, .NET Standard and .NET 6 and later. It supports the full protocol version 1.0.0 with the major extensions, and its storage is pluggable, from a local disk store to Azure or S3.
- Who is it for?
- tusdotnet suits a team whose users upload large files over unreliable connections, because the protocol lets the client resume from the byte it reached instead of starting again, and the server side is a NuGet package with a few lines of configuration in an ASP.NET Core application.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 36 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The protocol and the server
The README opens with the Tus project's own description, and it is the clearest statement of the problem.
The 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, offering simple, cheap and reusable stacks for clients and servers, supporting any language, any platform and any network.
tusdotnet is the .NET server implementation of that protocol, and it runs on .NET Framework, .NET Standard and .NET 6 and later.
Why the protocol matters is worth a sentence of its own. A large upload over a mobile connection that drops at the ninety percent mark is the classic case where a plain HTTP upload fails, and where the only client side remedy is to send the whole file again. With a resumable protocol, the client asks the server how much has been stored, sends the remainder, and the transfer continues.
That design has a consequence for the server implementation that shows up in how tusdotnet is built. The server has to keep partial files, track offsets, and validate that the client resumes from the right place, which is why the storage abstraction is the most important extension point in the package rather than a detail.
What the feature list actually covers
The feature list is short and each item is specific.
It runs on .NET Framework, .NET Standard 1.3 and later and .NET 6 and later, using either OWIN or ASP.NET Core, so the same server code works in a self-hosted process, behind IIS or in a modern minimal API application.
Protocol support is listed as full support for Tus 1.0.0 including all the major extensions: checksum, checksum trailers, concatenation, creation, creation with upload, upload defer length, expiration and termination.
That list is the part to read carefully if you are choosing a Tus server. The extensions are where the interoperability differences live. Creation is the extension that lets a client register a file before uploading any of it, which is what makes a resumable upload possible at all, since the client needs a stable identifier to resume against. Upload defer length lets the size be decided later. Concatenation is how a client assembles a file from parts. Checksum is how the server verifies what arrived.
There is also experimental support for the IETF resumable uploads for HTTP draft, on a separate proof of concept branch. The word experimental is doing real work there, and a branch rather than a release is the honest way to ship it.
The remaining features are adjectives the README uses deliberately: fast and reliable, easy to configure, and customizable data storage.
Wiring it into an ASP.NET Core application
The getting started section is one package reference and one mapping call, which is the shape you would hope for.
dotnet add package tusdotnetThe mapping call is where the configuration happens.
Store = new tusdotnet.Stores.TusDiskStore(@"C:\tusfiles\"),
Events = new()
{
// What to do when the file is completely uploaded?
OnFileCompleteAsync = async eventContext =>
{
var file = await eventContext.GetFileAsync();
await QueueForProcessing(file);
}
}
});Two things about that design are worth noticing.
First, the callback that configures the endpoint is invoked on each request, and the comment in the README says so explicitly: it is called on each request so different configurations can be returned per user, domain or path, and returning null disables tusdotnet for the current request. That is a small decision with large consequences, because it means the store and the event handlers can be chosen per request rather than per application, which is what you need when different tenants use different storage or different processing pipelines.
Second, the completion event is the integration point with the rest of your application. The file is fetched from the event context and handed to your own processing queue, which keeps the upload path free of whatever your application does with the file once it has arrived.
The README also notes that depending on your infrastructure you may need to configure Kestrel, IIS or other reverse proxies, and it links the wiki pages for each.
Storage is the extension point
The storage section lists three options in a table, and the third option is the interesting one.
The built-in store is the disk store, which saves files to a local directory. That is enough for a single server and for development, and it is the store used in the getting started snippet.
Then there are community stores. One targets Azure Blob Storage. The other targets S3-compatible storage, with the README naming AWS S3, MinIO and Cloudflare R2 as the services it is meant for.
That pair of community packages is a sign of how the project is organised. The core package does not ship a cloud storage client, which means it does not drag an Azure or AWS SDK into every application that uses it, and the storage backends live in separate packages that a deployment opts into.
And you can write your own store, with a wiki page describing how. That is the right way round for a server whose main job is to move bytes reliably: the protocol handling is the part that should be standardised, and where the bytes land is the part that should fit the deployment.
The README also links the tus.io implementations page, which lists clients for a number of platforms, Android, Java, JavaScript and iOS among them, and notes that tusdotnet should work with all of them as long as they support version 1.0.0 of the protocol.
Trying it out locally
The way to evaluate a protocol server is to run the real client against it, and the repository is set up for exactly that.
Clone the repository and run one of the test sites, each of which launches a small site running tusdotnet together with the official JavaScript client, so that the protocol can be tested on your own machine.
That is a better test harness than a unit test suite for this kind of project, because the point of Tus is interoperability with clients you did not write. The repository holds a source directory with the packages, a documentation directory, a tools directory, and a well-known directory, which is where a Tus server advertises its capabilities to clients.
The codecov badge in the readme shows that coverage is tracked, and the NuGet badges show the package version and download count, which is the standard measure of whether a .NET library is actually in use.
The release history gives the pace. The tags are 2.12 from 2026-09-19, 2.11.2 from 2026-06-24 and 2.11.1 from 2026-02-12, and the last push was on 2026-09-19. So this is an actively maintained package on a 2.x line with regular releases, which is what you want from something that sits in the path of every large file your users send.
Licence, hosting and what to check
The licence is MIT, with the file at the root of the repository, and the package is published to NuGet under the name tusdotnet.
The hosting question is the one with the most operational weight, and the README sends you to three separate wiki pages depending on your infrastructure: configuring Kestrel, configuring IIS, and configuring other reverse proxies.
That trio tells you the deployment story. Tus relies on HTTP headers to carry the upload offset and the protocol tokens, and a reverse proxy that buffers, rewrites or drops unknown headers will break the protocol in ways that are hard to diagnose, because the client simply fails to resume. If you put tusdotnet behind nginx or a load balancer, that configuration is not optional.
Three checks before you adopt it. That the client you have, or the client your users' devices will use, speaks Tus version 1.0.0, since the server targets that version. That the extensions you depend on are enabled on both ends, particularly creation if you want clients to start an upload before the bytes arrive. And that your storage choice handles the failure case, since a resumable upload means partial files persist on the server between attempts, and a store that treats a partial file as a complete one will quietly corrupt uploads.
Editorial conclusion
tusdotnet suits a team whose users upload large files over unreliable connections, because the protocol lets the client resume from the byte it reached instead of starting again, and the server side is a NuGet package with a few lines of configuration in an ASP.NET Core application. It is the wrong choice if your uploads are small enough to survive a single request, and the wrong choice if you need the emerging IETF standard rather than the Tus protocol, since the README marks that support as experimental on a separate branch. Verify first which protocol version your client speaks, that the extension you depend on, such as creation or checksum, is enabled on both sides, and that your reverse proxy passes the upload headers through unchanged.
Frequently asked questions
What is tusdotnet?
It is a .NET server implementation of the Tus protocol for resumable file uploads over HTTP, running on .NET Framework, .NET Standard and .NET 6 and later, hosted with OWIN or ASP.NET Core.
Which parts of the Tus protocol does tusdotnet support?
The README states full support for Tus 1.0.0 including all the major extensions: checksum, checksum trailers, concatenation, creation, creation with upload, upload defer length, expiration and termination. Support for the IETF resumable uploads draft is marked experimental and lives on a separate branch.
Where can uploaded files be stored?
The built-in disk store saves files to a local directory, community packages target Azure Blob Storage and S3-compatible storage such as AWS S3, MinIO and Cloudflare R2, and you can write your own store against the documented interface.
How is tusdotnet configured in an ASP.NET Core app?
You map it with a call that takes a callback invoked on each request, so the store and the event handlers can differ per user, domain or path, and returning null disables it for that request. The completion event hands the finished file to your own processing.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/tusdotnet-tusdotnet)Was this useful?