在网络编程中,文件上传是一个常见需求,但处理大文件上传时,常常会遇到各种问题。例如,上传过程中网络连接中断或者浏览器崩溃,导致上传失败,用户不得不重新开始上传,这无疑增加了用户的负担。尤其在网络环境不佳的地区,这种情况更是常见。本文将探讨如何使用PHP和tus协议来解决大文件上传的问题。
tus是一个基于HTTP的开放协议,用于实现可恢复的文件上传。所谓可恢复,指的是在上传过程中如果发生中断,可以在中断点继续上传,而不必重新上传整个文件。这种中断可能是用户主动暂停,也可能是由于网络问题或服务器故障导致的意外中断。
tus协议在2017年5月被Vimeo采用,其主要优势在于标准化了文件上传过程,使得API开发者可以更专注于应用特定的代码,而不必过多关注上传过程本身。此外,使用tus协议上传文件的一个好处是,用户可以从一台设备开始上传,然后在另一台设备上继续上传同一个文件,这大大提升了用户体验。
要开始使用tus协议,首先需要添加依赖。使用Composer可以方便地添加tus-php依赖:
composer require ankitpokhrel/tus-php
tus-php是一个与框架无关的纯PHP服务器和客户端实现,支持tus可恢复上传协议v1.0.0。
创建一个简单的服务器来处理请求,示例如下:
<?php
$server = new \TusPhp\Tus\Server('redis');
$response = $server->serve();
$response->send();
exit(0);
需要配置服务器以响应特定的端点。例如,在Nginx中,可以这样配置:
location /files {
try_files $uri $uri/ /path/to/server.php?$query_string;
}
假设服务器URL是http://server.tus.local,根据上述Nginx配置,可以通过http://server.tus.local/files访问tus端点。
服务器设置好后,客户端可以使用tus-php客户端对象来分块上传文件。首先,创建一个简单的HTML表单来获取用户输入:
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="tus_file" id="tus-file" />
<input type="submit" value="Upload" />
</form>
表单提交后,需要执行几个步骤来处理上传:
$client = new \TusPhp\Tus\Client('http://server.tus.local');
$client->setKey($uploadKey)
->file($_FILES['tus_file']['tmp_name'], 'your file name');
如果不显式提供上传密钥,系统将自动生成一个密钥。
$client->file($_FILES['tus_file']['tmp_name'], 'your file name');
$uploadKey = $client->getKey();
上传一个分块:
$bytesUploaded = $client->upload($chunkSize);
下次上传时,可以使用相同的上传密钥继续上传。
$bytesUploaded = $client->setKey($uploadKey)->upload($chunkSize);
上传完成后,服务器会使用默认的sha256算法验证上传的文件,确保文件未损坏。
Uppy是一个由tus协议背后的团队开发的时尚、模块化的文件上传插件。可以使用Uppy无缝集成官方的tus-js-client与tus-php服务器。这意味着使用PHP实现服务器,JS实现客户端。
uppy.use(Tus, {
endpoint: 'https://server.tus.local/files/',
resume: true,
autoRetry: true,
retryDelays: [0, 1000, 3000, 5000]
});
更多详细信息和示例实现可以在Uppy文档中找到。
tus-php服务器支持concatenation扩展,能够将多个上传合并为一个,使客户端能够并行上传并上传非连续的分块。
部分文件上传的完整示例可以在相关资源中找到。
tus-php项目本身仍处于初期阶段,未来可能会有所变化。可以在示例文件夹中找到三种不同的实现示例。欢迎尝试并报告任何发现的问题。欢迎提交拉取请求和项目建议。