View all files | ||||
This library can be used to enable resumable (and potentially asynchronous) file uploads in any Java web application. This allows the users of your application to upload large files over slow and unreliable internet connections. The ability to pause or resume a file upload (after a connection loss or reset) is achieved by implementing the open file upload protocol tus (https://tus.io/). This library implements the server-side of the tus v1.0.0 protocol with all optional extensions.
The Javadoc of this library can be found at https://tus.desair.me/. As of version 1.0.0-3.0, this library requires Java 17+. For older Java versions, please use one of the 1.0.0-2.x releases.
The tus-java-server library only depends on Jakarta Servlet API 6.0 and some Apache Commons utility libraries. This means that (in theory) you can use this library on any modern Java Web Application server like Tomcat, JBoss, Jetty... By default all uploaded data and information is stored on the file system of the application server (and currently this is the only option, see configuration section).
You can add the latest stable version of this library to your application using Maven by adding the following dependency:
The main entry point of the library is the me.desair.tus.server.TusFileUploadService.process(jakarta.servlet.http.HttpServletRequest, jakarta.servlet.http.HttpServletResponse) method. You can call this method inside a jakarta.servlet.http.HttpServlet, a jakarta.servlet.Filter or any REST API controller of a framework that gives you access to HttpServletRequest and HttpServletResponse objects. In the following list, you can find some example implementations:
Besides the core protocol, the library has all optional tus protocol extensions enabled by default. This means that the Tus-Extension header has value creation,creation-defer-length,checksum,checksum-trailer,termination,expiration,concatenation,concatenation-unfinished. Optionally you can also enable an unofficial download extension (see configuration section).
The first step is to create a TusFileUploadService object using its constructor. You can make this object available as a (Spring bean) singleton or create a new instance for each request. After creating the object, you can configure it using the following methods:
For now this library only provides filesystem based storage and locking options. You can however provide your own implementation of a UploadStorageService and UploadLockingService using the methods withUploadStorageService(UploadStorageService) and withUploadLockingService(UploadLockingService) in order to support different types of upload storage.
To process an upload request you have to pass the current jakarta.servlet.http.HttpServletRequest and jakarta.servlet.http.HttpServletResponse objects to the me.desair.tus.server.TusFileUploadService.process() method. Typical places were you can do this are inside Servlets, Filters or REST API Controllers (see examples).
Optionally you can also pass a String ownerKey parameter. The ownerKey can be used to have a hard separation between uploads of different users, groups or tenants in a multi-tenant setup. Examples of ownerKey values are user ID's, group names, client ID's...
Once the upload has been completed by the user, the business logic layer of your application needs to retrieve and do something with the uploaded bytes. For example it could read the contents of the file, or move the uploaded bytes to their final persistent storage location. Retrieving the uploaded bytes in the backend can be achieved by using the me.desair.tus.server.TusFileUploadService.getUploadedBytes(String uploadUrl) method. The passed uploadUrl value should be the upload url used by the client to which the file was uploaded. Therefor your application should pass the upload URL of completed uploads to the backend. Optionally, you can also pass an ownerKey value to this method in case your application chooses to process uploads using owner keys. Examples of values that can be used as an ownerKey are: an internal user identifier, a session ID, the name of the subpart of your application...
Using the me.desair.tus.server.TusFileUploadService.getUploadInfo(String uploadUrl) method you can retrieve metadata about a specific upload process. This includes metadata provided by the client as well as metadata kept by the library like creation timestamp, creator ip-address list, upload length... The method UploadInfo.getId() will return the unique identifier of this upload encapsulated in an UploadId instance. The original (custom generated) identifier object of this upload can be retrieved using UploadId.getOriginalObject(). A URL safe string representation of the identifier is returned by UploadId.toString(). It is highly recommended to consult the JavaDoc of both classes.
After having processed the uploaded bytes on the server backend (e.g. copy them to their final persistent location), it's important to cleanup the (temporary) uploaded bytes. This can be done by calling the me.desair.tus.server.TusFileUploadService.deleteUpload(String uploadUri) method. This will remove the uploaded bytes and any associated upload information from the storage backend. Alternatively, a client can also remove an (in-progress) upload using the termination extension.
Next to removing uploads after they have been completed and processed by the backend, it is also recommended to schedule a regular maintenance task to clean up any expired uploads or locks. Cleaning up expired uploads and locks can be achieved using the me.desair.tus.server.TusFileUploadService.cleanup() method.
This tus protocol implementation has been tested with the Uppy file upload client. This repository also contains many automated integration tests that validate the tus protocol server implementation using plain HTTP requests. So in theory this means we're compatible with any tus 1.0.0 compliant client.
This artifact is versioned as A.B.C-X.Y where A.B.C is the version of the implemented tus protocol (currently 1.0.0) and X.Y is the version of this library.
This library comes without any warranty and is released under a MIT license. If you encounter any bugs or if you have an idea for a useful improvement you are welcome to open a new issue or to create a pull request with the proposed implementation. Please note that any contributed code needs to be accompanied by automated unit and/or integration tests and comply with the defined code-style.
All pull requests should have the correct formatting according to Google Java Style code formatting. To verify if the code style is correct run:
To reformat your code run:
See the Google Java Style Github page on recommendations on how to configure this in your IDE. Or if you have Python 3, you can also use pre-commit to make your live easier: