TUS concatenation support

Chris Lu committed 2026-08-10 11:46:47 -07:00
1 parent ad7a920bad
commit 3c463e7cd2
1 file changed
+54 -3
+54 -3
@@ -6,6 +6,7 @@ SeaweedFS supports the [TUS](https://tus.io) protocol for resumable file uploads
- **Resumable uploads**: Resume interrupted uploads without re-sending data
- **Chunked uploads**: Upload large files in smaller pieces
- **Parallel uploads**: Upload parts of a file concurrently and concatenate them server-side
- **Simple protocol**: Standard HTTP methods with custom headers
- **Wide client support**: Libraries available for JavaScript, Python, Go, Java, and more
@@ -68,6 +69,7 @@ weed server -filer=true -filer.tusBasePath=
- `creation`: Create new upload sessions
- `creation-with-upload`: Upload data in the creation request
- `termination`: Cancel/delete uploads
- `concatenation`: Concatenate completed partial uploads into one file, enabling parallel uploads
## Usage Examples
@@ -82,7 +84,7 @@ Response headers:
```
Tus-Resumable: 1.0.0
Tus-Version: 1.0.0
Tus-Extension: creation,creation-with-upload,termination
Tus-Extension: creation,creation-with-upload,termination,concatenation
Tus-Max-Size: 5368709120
```
@@ -153,6 +155,51 @@ curl -X DELETE http://localhost:8888/.tus/.uploads/abc123-uuid \
-H "Tus-Resumable: 1.0.0"
```
### 7. Parallel Upload with Concatenation
Upload parts of one file concurrently as partial uploads, then concatenate them in order:
```bash
# Create a partial upload per part (Upload-Length is that part's size)
curl -i -X POST http://localhost:8888/.tus/path/to/file.txt \
-H "Tus-Resumable: 1.0.0" \
-H "Upload-Concat: partial" \
-H "Upload-Length: 500"
# Location: /.tus/.uploads/part1-uuid
curl -i -X POST http://localhost:8888/.tus/path/to/file.txt \
-H "Tus-Resumable: 1.0.0" \
-H "Upload-Concat: partial" \
-H "Upload-Length: 500"
# Location: /.tus/.uploads/part2-uuid
# Upload the parts, concurrently if desired
curl -X PATCH http://localhost:8888/.tus/.uploads/part1-uuid \
-H "Tus-Resumable: 1.0.0" \
-H "Upload-Offset: 0" \
-H "Content-Type: application/offset+octet-stream" \
--data-binary @part1.bin &
curl -X PATCH http://localhost:8888/.tus/.uploads/part2-uuid \
-H "Tus-Resumable: 1.0.0" \
-H "Upload-Offset: 0" \
-H "Content-Type: application/offset+octet-stream" \
--data-binary @part2.bin &
wait
# Concatenate the completed partials, in order, into the final file
curl -X POST http://localhost:8888/.tus/path/to/file.txt \
-H "Tus-Resumable: 1.0.0" \
-H "Upload-Concat: final;/.tus/.uploads/part1-uuid /.tus/.uploads/part2-uuid"
```
Notes:
- A completed partial does not appear at the target path; the file is created by the final request.
- The final request must not include `Upload-Length`; the file size is the sum of the partial sizes, capped by `-tusMaxSizeMB`.
- All listed partials must be finished before concatenation; concatenating an unfinished partial fails.
- Concatenation consumes the partials, so each partial can be used only once.
- Partials that are never concatenated expire like any other session after `-tusSessionExpiry`.
## TUS Headers
### Request Headers
@@ -163,6 +210,7 @@ curl -X DELETE http://localhost:8888/.tus/.uploads/abc123-uuid \
| `Upload-Length` | POST | Total file size in bytes |
| `Upload-Offset` | PATCH | Current byte offset |
| `Upload-Metadata` | Optional | Base64-encoded key-value pairs |
| `Upload-Concat` | Optional | `partial` creates a partial upload; `final;<url1> <url2> ...` concatenates completed partials |
| `Content-Type` | PATCH | Must be `application/offset+octet-stream` |
| `Content-Length` | PATCH | Size of data being uploaded |
@@ -201,6 +249,8 @@ const file = document.querySelector("input[type=file]").files[0];
const upload = new tus.Upload(file, {
endpoint: "http://localhost:8888/.tus/uploads/",
retryDelays: [0, 3000, 5000, 10000, 20000],
parallelUploads: 3, // uses the concatenation extension
metadata: {
filename: file.name,
filetype: file.type,
@@ -267,9 +317,10 @@ func main() {
## Limitations
- Maximum upload size: 5GB by default, configurable with `-tusMaxSizeMB`
- Maximum upload size: 5GB by default, configurable with `-tusMaxSizeMB`; a concatenated file's total size is capped by the same limit
- Session expiration: 24 hours by default, configurable with `-tusSessionExpiry`; expired sessions are removed by an hourly background cleanup
- Only single-file uploads (no concatenation extension)
- Concatenation partials are single-use: once concatenated into a final upload they are consumed and cannot be reused
- `concatenation-unfinished` is not supported: all partials must be complete before the final request
## See Also