SolidTUS 0.0.10
See the version list below for details.
dotnet add package SolidTUS --version 0.0.10
NuGet\Install-Package SolidTUS -Version 0.0.10
<PackageReference Include="SolidTUS" Version="0.0.10" />
paket add SolidTUS --version 0.0.10
#r "nuget: SolidTUS, 0.0.10"
// Install SolidTUS as a Cake Addin #addin nuget:?package=SolidTUS&version=0.0.10 // Install SolidTUS as a Cake Tool #tool nuget:?package=SolidTUS&version=0.0.10
What is it?
A C# dotnet 6 implementation of the TUS-protocol for resumable file uploads for an ASP.NET Core application.
Why create another TUS library?
This library's purpose is to be simple and give the consumer more options on how to authorize and authenticate requests.
Which I felt that other libraries did not provide.
SolidTUS is a more Controller/Action oriented and integrates well with a Web API or an MVC project.
If you have any suggestions or improvements please do not hesitate to contribute.
Other TUS libraries for C#
Install
Run dotnet add package solidTUS
Configuration
The required configuration is to register the services in the startup process:
// Register TUS services
builder.Services.AddTUS();
Usage
Then in the Controller
you mark the 2 actions that will be the TUS file creation endpoint with a TusCreation
-attribute and the upload action with a TusUpload
-attribute:
Each Action
will be injected with a context class: TusCreationContext
and TusUploadContext
.
[TusCreation]
public async Task<ActionResult> CreateUpload(TusCreationContext context)
{
// ... Construct a file ID and an URL route to the Upload endpoint
var fileID = "myFileID";
var url = "/url/path/to/upload/action/myFileID";
// When ready to create resource metadata
await context.StartCreationAsync(fileID, url);
return NoContent();
}
For the upload action:
[TusUpload]
[RequestSizeLimit(5_000_000_000)] // <-- example: Set upload size for the action to 5 Gib
[Route("url/path/to/upload/action/{fileId}")]
public async Task<ActionResult> Upload(string fileId, TusUploadContext context)
{
// ... stuff
await context.StartAppendDataAsync(fileId);
// Important must return 204 on success (TUS-protocol)
return NoContent();
}
TUS-features
- Core-protocol v.1.0.0 (stop and resume uploads)
- Creation (create upload)
- Creation-with-upload (upload and create in a single step)
- Checksum (validate partial uploads with a given algorithm and checksum)
- Max-size (define a hard limit for upload size)
- Tus-metadata validation
- Options (server feature announcements)
Eventual future features (not implemented):
- Expiration (deletion of unfinished uploads)
- Concatenation (upload chunks and then combine the files)
Note that the checksum feature does not implement the trailing header feature, i.e. A checksum value must be provided upon sending the http request.
Extra options
Configurations
TUS configurations
// Custom metadata provider or set maximum TUS protocol file size
builder.Services
.AddTUS()
.Configuration(options =>
{
// A Func<string, bool> that validates the given TUS-metadata upon resource creation
options.MetadataValidator = (metadata) => metadata.ContainsKey("filename");
// This max size is different than the ASP.NET specified max size. To change the request size limit do it per Action with an attribute (recommended).
options.MaxSize = 5_000_000_000;
});
Note: to change request size limits see: Microsoft documentation
If you don't want to use the default FileUploadStorageHandler you can provide your own, maybe you want to save the files to a database?
// Add custom storage handler
builder.Services
.AddTUS()
.AddStorageHandler<MyStorageHandler>(); // <-- must implement IUploadStorageHandler interface
If you want to support more checksum validators. The default checksum validators are: SHA1 and MD5:
// Add custom checksum validator
builder.Services
.AddTUS()
.AddChecksumValidator<MyChecksumValidator>(); // <-- must implement IChecksumValidator interface
If you use the default FileUploadStorageHandler you can configure the directory where to store files:
// Add custom checksum validator
builder.Services
.AddTUS()
.FileStorageConfiguration(options =>
{
options.DirectoryPath = "path/to/where/save/upload/files";
});
Configuration from appSettings.json or environment variables
You can configure the Tus-Max-Size
parameter and the default file storage upload folder from the appSettings.json configuration:
{
"SolidTUS": {
"DirectoryPath": "/path/to/my/uploads",
"MaxSize": "3000000"
}
}
Environment variables are named as SolidTUS__DirectoryPath
with a double underscore (so they also can be read from a linux environment). See Microsofts documentation for naming
Contexts
The injected context classes are excluded from ModelBinding but do show up in Swagger SwashBuckle. Excluding the contexts from the Swagger document, will be left as an exercise for the reader.
TusUploadContext
Is responsible for starting or terminating the upload. A termination is a premature ending and signals to the client that the upload has been terminated.
The class contains the following members:
UploadFileInfo
- Upload file metadata (file size, offset, TUS-metadata and id)OnUploadFinished
- A method that takes an awaitable callback. When the whole file has been completely uploaded the callback is invoked.StartAppendDataAsync
- Starts accepting the upload stream from the clientTerminateUpload
- Returns an error http response (default: 400 BadRequest)
MUST call either StartAppendDataAsync
or TerminateUpload
method. Cannot call both in a single request (you can't accept and not accept an upload).
The TusUploadContext
is injected from the TusUpload
-attribute.
TusUploadAttribute
Is responsible for marking the TUS-protocol upload endpoint. And needs information about 2 things:
- The file ID parameter name of type
string
- The context parameter name of type
TusUploadContext
These parameters can be tuned:
[TusUpload(FileIdParameterName = "Id", ContextParameterName = "tus")]
public async Task<ActionResult> UploadEndPoint(string Id, TusUploadContext tus)
{
/* Logic omitted ... */
}
TusCreationContext
Is responsible for creating the resource metadata UploadFileInfo
. Defining the file ID and eventual any TUS-metadata.
SolidTUS implements the TUS-protocol extension creation-with-upload
thus a resource creation can contain some upload data.
Before reaching the actual Action
method the metadata validator defined in the Configuration
will run; If metadata is invalid an automatic response of 400 Bad Request will be returned, as specified in the TUS-protocol.
The class contains the following members:
StartCreationAsync
- Starts resource creationOnResourceCreated
- A method that takes a callback function, which is invoked when the resource has been successfully createdOnUploadFinished
- A method that takes a callback function, which is invoked when the partial file or whole file has finished uploading. It could be the client has sent a partial upload or the whole file.Metadata
- ADictionary<string, string>
property of the parsed TUS-metadata
The TusCreationContext
is injected from the TusCreation
-attribute.
TusCreationAttribute
Is responsible for marking the TUS-creation endpoint and needs information about the context parameter name.
[TusCreation(ContextParameterName = "creationContext")]
public async Task<ActionResult> CreationEndPoint(TusUploadContext creationContext)
{
/* Logic omitted ... */
}
The TUS protocol with SolidTUS simplified
In essence the client sends a request to an endpoint (as marked by the TusCreation
attribute:
POST /files HTTP/1.1
Host: tus.example.org
Content-Length: 0
Upload-Length: 100
Tus-Resumable: 1.0.0
The server then knows to expect an upload file with a total size of 100 bytes and at which point SolidTUS creates an UploadFileInfo
which contains this metadata.
The server responds on success where the file can be uploaded:
HTTP/1.1 201 Created
Location: https://tus.example.org/files/24e533e02ec3bc40c387f1a0e460e216
Tus-Resumable: 1.0.0
In this example the file has an ID of 24e533e02ec3bc40c387f1a0e460e216.
The client then uploads the data to that location as marked by the TusUpload
attribute:
PATCH /files/24e533e02ec3bc40c387f1a0e460e216 HTTP/1.1
Host: tus.example.org
Content-Type: application/offset+octet-stream
Content-Length: 30
Upload-Offset: 70
Tus-Resumable: 1.0.0
[remaining 30 bytes]
The upload starts from byte 70 and has a total size of 100, the missing 30 bytes are in the PATCH body. This data is directed to the OnPartialUploadAsync
method in the IUploadStorageHandler
.
On success the server responds:
HTTP/1.1 204 No Content
Tus-Resumable: 1.0.0
Upload-Offset: 100
Test methodology
Using unit tests and manually making TUS-request with the official javascript client in the examples folder.
Dependencies
This package uses the C# functional extensions package, which can be a very opinionated library.
In the future I would like to not depend on this library so the consumer wouldn't have to deal with function pollutions.
References
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. 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. |
-
net6.0
- LanguageExt.Core (>= 4.2.9)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
0.0.34 | 149 | 2/2/2024 |
0.0.33 | 123 | 2/1/2024 |
0.0.32 | 144 | 1/12/2024 |
0.0.31 | 149 | 1/4/2024 |
0.0.30 | 134 | 1/4/2024 |
0.0.29 | 223 | 1/3/2024 |
0.0.28 | 137 | 1/2/2024 |
0.0.27 | 129 | 12/21/2023 |
0.0.26 | 130 | 12/18/2023 |
0.0.25 | 114 | 12/11/2023 |
0.0.24 | 108 | 12/11/2023 |
0.0.23 | 113 | 12/11/2023 |
0.0.22 | 126 | 12/7/2023 |
0.0.21 | 124 | 12/5/2023 |
0.0.20 | 144 | 10/9/2023 |
0.0.19 | 139 | 9/25/2023 |
0.0.18 | 147 | 9/23/2023 |
0.0.17 | 171 | 4/27/2023 |
0.0.16 | 422 | 8/8/2022 |
0.0.15 | 399 | 8/6/2022 |
0.0.14 | 411 | 8/5/2022 |
0.0.13 | 413 | 7/21/2022 |
0.0.12 | 403 | 7/21/2022 |
0.0.11 | 408 | 7/21/2022 |
0.0.10 | 431 | 7/13/2022 |
0.0.9 | 452 | 7/13/2022 |
0.0.8 | 439 | 7/13/2022 |
0.0.7 | 425 | 7/12/2022 |