SolidTUS 0.0.18
See the version list below for details.
dotnet add package SolidTUS --version 0.0.18
NuGet\Install-Package SolidTUS -Version 0.0.18
<PackageReference Include="SolidTUS" Version="0.0.18" />
paket add SolidTUS --version 0.0.18
#r "nuget: SolidTUS, 0.0.18"
// Install SolidTUS as a Cake Addin #addin nuget:?package=SolidTUS&version=0.0.18 // Install SolidTUS as a Cake Tool #tool nuget:?package=SolidTUS&version=0.0.18
What is it?
A C# dotnet 7 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.
Current TUS features
SolidTUS currently implements the following.
Basic features:
- Core-protocol v.1.0.0 (stop and resume uploads)
- Max-size (define a hard limit for upload size)
- Tus-metadata validation
- Options (server feature announcements)
Extensions:
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.
Only termination announcement in OPTION request is implemented.
The actual functionality must be implemented by yourself. See examples and documentation on how to and why.
Future goals is to implement all the extensions:
Other TUS libraries for C#
Quickstart
Add the package to your project:
$ `dotnet add package SolidTUS`
Register the service in the startup process:
// Register TUS services
builder.Services.AddTUS();
In your Controller
add the TusCreation
-attribute to the action method endpoint and the TusCreationContext
as parameter.
[TusCreation]
public async Task<ActionResult> CreateUpload([FromServices] 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();
}
This will not upload any file (unless the client explicitly uses the TUS-extension Creation-With-Upload
feature).
This only sets the ground work for getting information such as file size, and where to upload the data.
Next the actual upload.
Set the TusUpload
-attribute and add the TusUploadContext
as a parameter
[TusUpload]
[Route("url/path/to/upload/action/{fileId}")]
public async Task<ActionResult> Upload(string fileId, [FromServices] TusUploadContext context)
{
// ... stuff
await context.StartAppendDataAsync(fileId);
// Important must return 204 on success (TUS-protocol)
return NoContent();
}
And done...
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";
});
another option is to determine where each file should be uploaded on per upload basis. In the Controller
you can specify the file path:
[TusUpload]
public async Task<ActionResult> Upload(string fileId, [FromServices] TusUploadContext context)
{
// ... omitted
await context.StartAppendDataAsync(fileId, "determine/path/per/upload");
// ... omitted
}
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. To exclude from Swagger SwashBuckle you can annotate the contexts with the FromServices
-attribute.
IMPORTANT: Callbacks must be defined before upload starts.
The StartCreationAsync
and StartAppendDataAsync
starts upload.
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:
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]
After some while 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
.
When finished successfully 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.
TODO
- Create wiki pages for all the configuration options
- Create wiki pages for library design, and how to extend
- Implement all TUS extension features
References
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net7.0 is compatible. 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. |
-
net7.0
- No dependencies.
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 | 147 | 2/2/2024 |
0.0.33 | 121 | 2/1/2024 |
0.0.32 | 142 | 1/12/2024 |
0.0.31 | 145 | 1/4/2024 |
0.0.30 | 132 | 1/4/2024 |
0.0.29 | 221 | 1/3/2024 |
0.0.28 | 135 | 1/2/2024 |
0.0.27 | 127 | 12/21/2023 |
0.0.26 | 128 | 12/18/2023 |
0.0.25 | 112 | 12/11/2023 |
0.0.24 | 105 | 12/11/2023 |
0.0.23 | 111 | 12/11/2023 |
0.0.22 | 124 | 12/7/2023 |
0.0.21 | 122 | 12/5/2023 |
0.0.20 | 144 | 10/9/2023 |
0.0.19 | 137 | 9/25/2023 |
0.0.18 | 145 | 9/23/2023 |
0.0.17 | 170 | 4/27/2023 |
0.0.16 | 420 | 8/8/2022 |
0.0.15 | 397 | 8/6/2022 |
0.0.14 | 408 | 8/5/2022 |
0.0.13 | 410 | 7/21/2022 |
0.0.12 | 401 | 7/21/2022 |
0.0.11 | 405 | 7/21/2022 |
0.0.10 | 429 | 7/13/2022 |
0.0.9 | 450 | 7/13/2022 |
0.0.8 | 437 | 7/13/2022 |
0.0.7 | 423 | 7/12/2022 |