TusPHP Resumable Uploads with a PHP Client and Server
🚀 A pure PHP server and client for the tus resumable upload protocol v1.0.0
At a glance
- What is it?
- TusPHP implements tus resumable upload protocol v1.0.0 for PHP applications, with a server, client, cache configuration, web server routing, and extension support. It suits applications that need to pause and resume large file transfers.
- Who is it for?
- TusPHP is appropriate for PHP applications that require tus-compatible resumable uploads and can operate Redis, APCu, or file-backed cache. It is less suitable when the deployment cannot disable nginx request buffering or when simple multipart uploads are sufficient.
- 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 95 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
TusPHP Resumable Upload Scope
TusPHP addresses interrupted large-file uploads in PHP applications. The project describes tus as an HTTP-based protocol for resumable uploads. A transfer can continue from the last completed position after a user pauses it or after a network or server interruption. The intended audience is PHP developers building clients that upload files too large or too slow for one reliable request. The project provides a server-side implementation and a PHP client, so it can run inside an existing PHP application.
The repository targets PHP 8.1 and newer. The README also documents an older Composer constraint for projects that use PHP 7.1, Symfony 3, or Symfony 4, but the current package installation path is for supported PHP versions. The implemented protocol is tus resumable upload protocol v1.0.0. TusPHP therefore fits applications that need explicit upload creation, offset handling, partial-transfer continuation, and deletion of incomplete uploads.
It does not replace every kind of file transfer. For small files or deployments where a standard multipart form is sufficient, resumable upload state and shared cache infrastructure may add complexity without a corresponding benefit. The protocol is most relevant when interrupted transfers impose repeated bandwidth costs, create a poor user experience, or require uploads to survive more than one request.
TusPHP Request and Cache Flow
The server entry point creates a `TusPhp\Tus\Server` instance and calls `serve()`. The returned response is then sent to the HTTP client. The server must be reachable through a dedicated endpoint because tus uses HTTP requests to create, extend, inspect, and manage uploads. The README uses `/files` as the example route and places the server implementation in `server.php`.
Upload state is kept in a cache. The server constructor accepts `redis`, `file`, or `apcu`, while an empty value selects file-based cache. The README explicitly says that file-based cache is not recommended for production. Redis is the backend in the basic server example. Redis settings can be supplied through `config/server.php` and `config/client.php`, or overridden for the server and client with the `REDIS_HOST`, `REDIS_PORT`, and `REDIS_DB` environment variables.
The cache records transfer progress between requests. When a client returns after a failed or paused upload, the server can report the stored offset and accept data from that position. If the cache is unavailable or the upload identity is invalid, this continuation path cannot work as intended. Cache persistence is consequently part of the resumable-upload design rather than an incidental storage choice.
The PHP client receives a base URL and requires a caller-supplied key. That key identifies the upload across calls. The client associates a local file with a filename and can send a bounded chunk. After an interruption, another `upload()` call continues from the server's recorded offset. `getOffset()` reports stored progress, and `delete()` removes a partial upload from the cache.
Install TusPHP and Configure the Upload Endpoint
Install the package through Composer. The README gives the current PHP installation command and a separate command for projects that still require the v1 line.
composer require ankitpokhrel/tus-phpThe current project information identifies PHP 8.1 and newer. The README also documents this legacy constraint:
composer require ankitpokhrel/tus-php:^1.2That older command is specifically associated with PHP 7.1, Symfony 3, or Symfony 4 environments.
Create the server entry point and route the upload endpoint to it. The documented server uses Redis and sends the protocol response directly to the caller.
<?php
$server = new \TusPhp\Tus\Server('redis');
$response = $server->serve();
$response->send();
exit(0); // Exit from current PHP process.With nginx, requests to `/files` should reach the PHP entry point. This configuration sends requests to `server.php` when the requested path does not exist as a static file.
location /files {
try_files $uri $uri/ /server.php?$query_string;
}With nginx and FastCGI, the README says request buffering must be disabled. Otherwise nginx may read the entire request body before passing it to PHP, preventing the application from receiving upload chunks early enough to support resumption.
location ~ \.php$ {
# ...
fastcgi_request_buffering off; # Disable request buffering
# ...
}The `/files` route is an example rather than a mandatory name. Whichever route is selected must match the base URL configured in the client.
TusPHP PHP Client Upload and Resume Example
The client API supports creating, resuming, inspecting, and deleting uploads. Its base URL must point to the server endpoint. The README states that a key is mandatory. An application that intends to resume a transfer must preserve and reuse the same logical key rather than generating an unrelated identity for every call.
The documented client example selects a file, sends a one-megabyte chunk, and then calls `upload()` again. Omitting the length parameter uploads the rest of the file.
$client = new \TusPhp\Tus\Client($baseUrl);
// Key is mandatory.
$key = 'your unique key';
$client->setKey($key)->file('/path/to/file', 'filename.ext');
// Create and upload a chunk of 1MB
$bytesUploaded = $client->upload(1000000);
// Resume, $bytesUploaded = 2MB
$bytesUploaded = $client->upload(1000000);
// To upload whole file, skip length param
$client->file('/path/to/file', 'filename.ext')->upload();`upload()` returns the number of bytes uploaded. Applications can use that value for progress reporting, although the README does not define a particular user-interface policy or failure callback.
Before resuming, the client can ask the server for its stored offset. The method returns `false` when the upload is absent or invalid, and a byte count when the upload is recognized.
$offset = $client->getOffset(); // 2000000 bytes or 2MBA partial upload can also be deleted from the cache.
$client->delete($key);The README excerpt does not document automatic handling of a changed local file, browser file selection, authentication headers, or checksum validation. Those behaviors should not be assumed without checking the relevant source or integration documentation.
TusPHP Expiration, Concatenation, and Upload Limits
The project lists expiration and concatenation as extension support. However, the displayed README does not include the configuration or code needed to activate either feature. Their inclusion in the table of contents confirms that these areas exist in the project, but it does not establish their production behavior. An adopter should consult the relevant repository documentation before depending on either extension.
The clearest production constraint is cache selection. Redis, file, and APCu are named as server cache options, and the README warns against file-based cache in production. Cache availability also affects resumption. If the server cannot retain the upload offset between requests, a later request cannot reliably continue the interrupted transfer.
The nginx constraint is equally concrete. According to the README, leaving `fastcgi_request_buffering` enabled prevents resumable uploads through nginx and FastCGI because nginx waits for the full request body before handing it to PHP. Disabling buffering can also help with request timeouts and temporary disk-space problems, as stated in the README.
The server's default maximum upload size is zero. The documentation interprets zero as no restriction. An application can replace that default with a byte limit through `setMaxUploadSize()`.
$server->setMaxUploadSize(100000000); // 100 MB in bytesThe unrestricted default may not match a production application's storage or abuse-control requirements. Setting an explicit limit does not, by itself, define the complete cleanup or authorization policy, which the README does not fully document here.
TusPHP Compared With Direct Multipart Uploads
A direct multipart form upload uses a different mechanism. It sends a file through a form submission and generally depends on one request completing successfully. If the connection fails near the end, the client may need to send the file again. TusPHP instead records an upload key and byte offset, then permits a later request to continue from that position.
That difference matters for long transfers, unstable connections, and workflows where users may pause deliberately. It also introduces components that a conventional form endpoint may not need: a tus-compatible route, server and client configuration, shared upload state, and proxy buffering controls. TusPHP is the better fit when interruption creates meaningful repeated bandwidth use or disrupts the application workflow. It is the wrong tool for small files when resumability is not a requirement or when the hosting environment cannot support a compatible cache and routing configuration.
This is an architectural comparison rather than a list of interchangeable packages. A team choosing a direct multipart endpoint accepts one-request transfer semantics in exchange for a simpler request path. A team choosing TusPHP accepts additional state and infrastructure in exchange for offset-based continuation.
TusPHP Maintenance, Releases, and License
The repository is not archived, and the last push was on 2026-07-20. The latest listed release is `v2.4.0`, dated 2024-04-06. Earlier releases include `v2.3.0`, dated 2022-09-18, and `v2.2.1`, dated 2022-03-31. This release history means an upgrade decision should compare the currently deployed version with `v2.4.0` rather than assuming that the existence of a newer commit corresponds to a newer package release.
The README includes a v1 Composer path for older PHP and Symfony environments. That legacy path is relevant when upgrading an existing application, but the repository does not document a general upgrade procedure in the displayed text. Release compatibility and migration work must therefore be checked against the version selected by Composer.
The repository is licensed under MIT. That identifies the license, but this review does not provide legal advice. Application owners still need to read the `LICENSE` file and address their own hosting, privacy, retention, and file-processing requirements.
The repository includes `Makefile` targets for Docker development, Composer installation, linting, tests, and coverage. The documented development quick start is `make dev`, while `make dev8` selects the PHP 8 image. These commands support work on the repository, but the README excerpt does not turn them into a production deployment procedure.
Editorial conclusion
TusPHP is appropriate for PHP applications that require tus-compatible resumable uploads and can operate Redis, APCu, or file-backed cache. It is less suitable when the deployment cannot disable nginx request buffering or when simple multipart uploads are sufficient. Before adoption, verify the web server route, cache lifecycle, upload size limit, expiration policy, and stable client keys. For a PHP 8.1+ tus deployment, the documented `composer require ankitpokhrel/tus-php` setup is the concrete starting point.
Frequently asked questions
How do I install TusPHP for resumable uploads in PHP?
The README instructs users to install it with Composer using `composer require ankitpokhrel/tus-php`. It also documents `composer require ankitpokhrel/tus-php:^1.2` for projects using PHP 7.1, Symfony 3, or Symfony 4.
How does TusPHP resume an interrupted file upload?
The client sends an upload key and file information, then calls `upload()` with a byte limit. The server stores the upload offset in its configured cache, and a later `upload()` call continues from the recorded position. `getOffset()` can inspect stored progress.
Which cache backends can TusPHP use?
The README names Redis, file, and APCu, with an empty value selecting file-based cache. It says that file-based cache is not recommended for production use and documents Redis configuration through files and environment variables.
What configuration is required for nginx uploads?
The server route must send `/files` requests to the PHP entry point. For nginx with FastCGI, the README says `fastcgi_request_buffering` should be set to `off`, because buffering can delay PHP requests until the full body has been received.
Can the TusPHP client delete a partial upload?
Yes. The documented client API includes `delete($key)`, which deletes a partial upload from the cache. The client also provides `getOffset()` to check whether a partial upload exists and how many bytes are recorded.
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/ankitpokhrel-tus-php)Was this useful?