finn1990/tus-php

适用于 tus 可续传上传协议 v1.0.0 的纯 PHP 服务器和客户端

dev-master 2018-05-11 16:58 UTC

This package is auto-updated.

Last update: 2024-09-13 06:08:45 UTC


README

警告:该项目处于初始阶段。一些实现可能在将来发生变化。请随意尝试并报告任何问题。欢迎提交拉取请求和项目建议!

Tus PHP

PHP Version Build Code Coverage Scrutinizer Code Quality Download Software License

使用 tus 可续传上传协议 v1.0.0 在 PHP 中实现文件可续传上传.

概述

tus 是一种基于 HTTP 的可续传文件上传协议。可续传意味着在发生中断的情况下,您可以继续上传而无需重新上传整个数据。中断可能是用户有意愿地暂停,也可能是由于网络问题或服务器故障等意外情况。

Tus PHP demo

资源

  1. Medium 文章
  2. Laravel/Lumen 集成

安装

通过 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

请确保您系统中已安装DockerDocker Compose。然后,从项目根目录运行Docker脚本。

$ bin/docker.sh

现在,客户端可以通过http://0.0.0.0:8080访问,服务器可以通过http://0.0.0.0:8081访问。默认API端点设置为/files,上传的文件可以在uploads文件夹中找到。所有的Docker配置都可以在docker/文件夹中找到。

使用minikube的Kubernetes

请确保您系统中已安装minikubekubectl。然后,从项目根目录使用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中根据需要调整它。

贡献

  1. 如果您还没有安装,请安装PHPUnitcomposer
  2. 安装依赖项
    $ composer install
  3. 使用phpunit运行测试
    $ ./vendor/bin/phpunit
  4. 验证更改是否符合PSR2编码标准
    $ ./vendor/bin/php-cs-fixer fix <changes> --rules=@PSR2,not_operator_with_space,single_quote

关于这个项目的问题?

请随时报告您发现的任何错误。欢迎提交pull请求、问题和项目建议!