finn1990 / tus-php
适用于 tus 可续传上传协议 v1.0.0 的纯 PHP 服务器和客户端
Requires
- php: ^7.1.3
- guzzlehttp/guzzle: ^6.3
- nesbot/carbon: ^1.26
- predis/predis: ^1.1
- ramsey/uuid: ^3.7
- symfony/console: ^2.8
- symfony/http-foundation: ^2.8
Requires (Dev)
- mockery/mockery: ^1.0@dev
- php-mock/php-mock: dev-master
- phpunit/phpunit: 6.5.x-dev
This package is auto-updated.
Last update: 2024-09-13 06:08:45 UTC
README
警告:该项目处于初始阶段。一些实现可能在将来发生变化。请随意尝试并报告任何问题。欢迎提交拉取请求和项目建议!
Tus PHP
使用 tus 可续传上传协议 v1.0.0 在 PHP 中实现文件可续传上传.
概述
tus 是一种基于 HTTP 的可续传文件上传协议。可续传意味着在发生中断的情况下,您可以继续上传而无需重新上传整个数据。中断可能是用户有意愿地暂停,也可能是由于网络问题或服务器故障等意外情况。
资源
安装
通过 composer 拉取包。
$ composer require ankitpokhrel/tus-php:dev-master
使用
服务器
这是一个简单服务器的样子。
// server.php $server = new \TusPhp\Tus\Server('redis'); // Leave empty for file based cache $response = $server->serve(); $response->send(); exit(0); // Exit from current PHP process.
您需要重新编写服务器以响应特定的端点。例如
Nginx
# nginx.conf location /files { try_files $uri $uri/ /server.php?$query_string; }
Apache
# .htaccess RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^files/?(.*)?$ /server.php/$1 [QSA,L]
默认最大上传大小为 0,表示没有限制。您可以按以下说明设置最大上传大小。
$server->setMaxUploadSize(100000000); // 100 mb in bytes
客户端
客户端可用于创建、继续和/或删除上传。
$client = new \TusPhp\Tus\Client($baseUrl, 'redis'); // Leave second parameter empty for file based cache // Optional. If a key is not set explicitly, the system will generate a unique uuid. $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();
要检查文件是否之前已部分上传,您可以使用 getOffset
方法。如果上传不存在或无效,则返回 false;否则返回已上传的总字节数。
$offset = $client->getOffset(); // 2000000 bytes or 2mb
从缓存中删除部分上传。
$client->delete($key);
默认情况下,客户端使用 /files
作为 API 路径。您可以使用 setApiPath
方法更改它。
$client->setApiPath('/api');
默认情况下,服务器将使用 sha256
算法来验证上传的完整性。如果您想使用不同的哈希算法,可以使用 setChecksumAlgorithm
方法。要获取支持的哈希算法列表,可以向服务器发送 OPTIONS
请求。
$client->setChecksumAlgorithm('crc32');
扩展支持
- 创建扩展基本上已实现,用于创建上传。目前无法延迟上传的长度。
- 终止扩展已实现,用于终止已完成和未完成的上传,以便服务器可以释放使用的资源。
- 已实现校验和扩展,服务器将默认使用
sha256
算法来验证上传。 - 已实现过期扩展,详细信息见下文。
- 此连接扩展已实现,但服务器无法处理未完成连接。
过期
服务器能够删除过期的但未完成的上传。您可以手动使用以下命令或在 cron 作业中删除它们。
$ ./vendor/bin/tus tus:expired --help Usage: tus:expired [<cache-adapter>] Arguments: cache-adapter Cache adapter to use, redis or file. Optional, defaults to file based cache. eg: $ ./vendor/bin/tus tus:expired redis
连接
服务器能够将多个上传合并为一个,使客户端能够执行并行上传并上传非连续块。
// Actual file key $uploadKey = uniqid(); $client->setKey($uploadKey)->file('/path/to/file', 'chunk_a.ext'); // Upload 10000 bytes starting from 1000 bytes $bytesUploaded = $client->seek(1000)->upload(10000); $chunkAkey = $client->getKey(); // Upload 1000 bytes starting from 0 bytes $bytesUploaded = $client->setFileName('chunk_b.ext')->seek(0)->upload(1000); $chunkBkey = $client->getKey(); // Upload remaining bytes starting from 11000 bytes (10000 + 1000) $bytesUploaded = $client->setFileName('chunk_c.ext')->seek(11000)->upload(); $chunkCkey = $client->getKey(); // Concatenate partial uploads $client->setFileName('actual_file.ext')->concat($uploadKey, $chunkAkey, $chunkBkey, $chunkCkey);
此外,服务器还将验证校验和与合并的文件,以确保文件没有损坏。
中间件
您可以使用中间件来操作服务器的请求和响应。中间件可以在服务器调用实际 handle 方法之前运行一段代码。您可以使用中间件进行身份验证、处理 CORS、白名单/黑名单 IP 等。
创建中间件
为了创建中间件,您需要实现 TusMiddleware
接口。handle 方法提供了请求和响应对象,以便您进行操作。
<?php namespace Your\Namespace; use TusPhp\Request; use TusPhp\Response; use TusPhp\Middleware\TusMiddleware; class Authenticated implements TusMiddleware { // ... /** * {@inheritDoc} */ public function handle(Request $request, Response $response) { // Check if user is authenticated if (! $this->user->isLoggedIn()) { throw new UnauthorizedHttpException('User not authenticated'); } $request->getRequest()->headers->set('Authorization', 'Bearer ' . $this->user->token()); } // ... }
添加中间件
要添加中间件,从服务器获取中间件对象并简单传递中间件类。
$server->middleware()->add(Authenticated::class, AnotherMiddleware::class);
或者,您也可以传递中间件类对象。
$authenticated = new Your\Namespace\Authenticated(new User()); $server->middleware()->add($authenticated);
跳过中间件
如果您想跳过或忽略任何中间件,您可以使用skip
方法来实现。
$server->middleware()->skip(Cors::class, AnotherMiddleware::class);
与Uppy兼容
Uppy是由tus协议背后的同一团队开发的一款简洁、模块化的文件上传插件。您可以使用Uppy将官方的tus-js-client与tus-php服务器无缝集成。更多详细信息请查看Uppy文档。
uppy.use(Tus, { endpoint: 'https://tus-server.yoursite.com/files/', // use your tus endpoint here resume: true, autoRetry: true, retryDelays: [0, 1000, 3000, 5000] })
设置开发环境以及/或本地运行示例
本实现的基于ajax的示例可以在examples/
文件夹中找到。您可以选择使用Docker构建和运行它,或者在本地使用minikube配合kubernetes。
Docker
请确保您系统中已安装Docker和Docker Compose。然后,从项目根目录运行Docker脚本。
$ bin/docker.sh
现在,客户端可以通过http://0.0.0.0:8080访问,服务器可以通过http://0.0.0.0:8081访问。默认API端点设置为/files
,上传的文件可以在uploads
文件夹中找到。所有的Docker配置都可以在docker/
文件夹中找到。
使用minikube的Kubernetes
请确保您系统中已安装minikube和kubectl。然后,从项目根目录使用k8s脚本构建和启动容器。
$ bin/k8s.sh
该脚本将为minikube设置docker环境,在本地构建所有必需的Docker镜像,创建kubernetes对象,并在端口30020
上提供服务。构建成功后,客户端可以通过http://192.168.99.100:30020访问,服务器可以通过http://192.168.99.100:30021访问。
脚本默认创建1个客户端副本和3个服务器副本。所有的kubernetes配置可以在k8s/
文件夹中找到,您可以根据需要对其进行修改。
在minikube中使用时,您可以使用另一个辅助脚本列出所有上传的文件,登录到redis并清除redis缓存。
# List all uploads $ bin/minikube.sh uploads # Login to redis $ bin/minikube.sh redis # Clear redis cache $ bin/minikube.sh clear-cache
由于服务器支持tus过期扩展,已设置一个cron作业,每天午夜运行一次以释放服务器资源。您可以在k8s/cron.yml
中根据需要调整它。
贡献
- 如果您还没有安装,请安装PHPUnit和composer。
- 安装依赖项
$ composer install
- 使用phpunit运行测试
$ ./vendor/bin/phpunit
- 验证更改是否符合PSR2编码标准
$ ./vendor/bin/php-cs-fixer fix <changes> --rules=@PSR2,not_operator_with_space,single_quote
关于这个项目的问题?
请随时报告您发现的任何错误。欢迎提交pull请求、问题和项目建议!