PHP中如何使用TUS协议来实现大文件的断点续传

PHP中如何使用TUS协议来实现大文件的断点续传

【相关学习推荐:php图文教程】

你是否曾经为大文件上传而苦恼?如果文件上传的过程中,因为某种原因中断了,是否可以从中断的位置继续上传,而不用重新上传整个文件?如果你有这样的困惑,那么请继续阅读下面的内容。

在现代网站应用中,上传文件是非常常见的。在任何语言中,通过使用一些工具,都可以实现文件上传的功能。但是,如果处理大文件上传的需求,还是有点麻烦的。J w &

假如你此时正在上传一个很大的文件,大约一个小时过去了,进度是 90%。突然断f | X h X网了或者浏览器崩溃了,上传的程序退? ] O 8 R X出,你要再全部重新来过。真的很不爽,对不对?还} { x k t t s d ;有更让人k k ] L 3 $ = g v郁闷的是,如果你的网速 j o P Q很慢,那么,无论你重来多少次,你都不可能上传成功。

PHP中如何使用TUS协议来实现大文件的断点续传

在 PHP 中,我们可以尝试利用 tus 协议的断点续传功能来解决这个问题。

什么是 tus?

Tus 是一个基于 HTTP 的 文件断点续传开放l | C .协议。 断点续传的意v ; E Q思是不管是用户自行中断,还是由于网络等原因的意外中断,都可以从中断的地方继续上传,而不用重新开始。

Tus 协议是在 2017年5月被 Vimeo 采用的。

为什么用 tus?; } [

引用 Vimeo 的博客:

我们之所以决定用 tus2 % 9 N ] s 7 J,是 d 因为它能以简洁开放的形式,将文件4 W E a = @上传的过程标准化。这种标准化有利于 API 的开发者更加专注于应用本身的逻辑} v ; 0 . ^,而非文件上传的过程。

使用这种方式上传的另一个好处是,你可以在笔记本上开始上传文件,然后又转到手机或者其他设备继续N n 6 B 7 5 g - )上传同一个文件,这可以极大地提升用户体验D C C 7 T y %

PHP中如何使用TUS协议来实现大文件的断点续传

图片: Tus 大致的工作流程

开始

第一步,加载依赖。

$ composer require ankitpokhrel/tus-php

tus-php 是用于 tus 断点续传协议 v1.0.0 的一个的纯 PHP 框架,完美实现了 服务端与客户端的交互 。

更新: 现在 Vimeo 官方 PHP 库 的 vr e b3 用的是 TusPHP。i ! m _ a 0

创建一个处理请求的服务

你可以像下面这样创建一个服务端.

// serverI i t b 0 t 9 ].php
$see % z D 2rver   = new \TusPhp\Tus\Server('x % + 3 S ~ m W !redis');
$response = $server->serve();
$response->send();
exit(0); // 退出当前 PHP 进程

你需要配置你的服务器以便能对特定的终端进行响应. 如果使用 Nginx 的话你可以像下面这样配P X 9 p M置:

# nginx.conf
location /files {
try_files $uri $uri/ /path/to/server.php?$query_string;
}

假设W 9 b o * O X我们服务端的 URL 是 http://serve[ y s 2 lr.tus.local. 因此, 基于我们上面的 Nginx 配置,我们可以通过 http://server.tus.local/files. 来访问到我们的 tus 终端.

基于 RESTful 风格的端点配置:

# 获取有关服务器目前配置的信[ Z H w W . 3 Y W息\
OPTIONS /files
# 检C W 3 | y v &查上传的文件是否合法\
HEAD /fil= ! L n Bes/{upload-key}
# 创建\
P] + p m 6OST /files
# 修改e o e\
Pa p B NATCH /files/@ J j{upload-key}
# 删除1 ~ h H u o I # {\
DELETj _ wE /fileF u Y a K g w Zs/{upload-key}

查看 协议细则 获取更多关于路由的信息。

如果你是用类似于 Laravel 的框架,那么你就不需要在配置文件里定义这些了, 可以直接~ ? W B ? D定义路由来访问 tus 的基础端点。我们会在另外的教程里_ @ W / b v ~ ; t介绍相关细节。

使用 tus-php 客户端处理上传

服务器到位后,客户端可以块的形式上传文件。 让我们首先创建一个简单的HTML表单v a S ` 来获取用户的输入。

<form action="upload.php" method="post" enctA ^ Vype="multipart/form-data">
<input type="file" name="tu# a #s_file" id="tus-file" />
<input type="submit" value="Upload" />E V Q 5 W X;
</form>

提交表单后,我们需要按照几个步骤来处理上传。

  1. 创建一个 tus-php 客户端对象
// Tus client
$client = new \TusPhp\Tus\Cl} r C  v p = $ .ient('http://server.tus.local');

上面代码中的第一个参数是你的tus服务器地址。

2.1 a x o 使用文件元数据初始化客户端

为了确保上传文件的唯一性,我们需要给每个上传的文件以唯一标识。这样在文件中断后续传的时候,Z l @ d v服务器就可以很清晰地辨识出,哪几个片段是属于同一个文件得。这个标识码可以自己指定,也可以由系统生K , I N ! M成。

// 设置标识码和文件元数据
$clie. ) - A  9 9 } nnt->setKey($uploadKey)
->fZ y g U X p _ Hile($_FILES['tus_file']['tmp_name'], 'your file name');

如果不想指定标识码,可以这样写,由系统会自动生成:l E N &

$client->file($_FILES['tus_file']['tmp_name'], 'yourC  4 file name');
$uploadKey = $client->getKey(); // Unique upload key

3. 分块上传文件

// $chunkSize 是以字节为单位的,例如 5000000 等于 5_ Q % MB
$bytesUpL d x - ` I q u Floaded = $client->s w n v ?;upload($chunkSize);

当你想要续传9 m @ X I c 5下一块的时候,就可以带上同样的标识码参数来续传。

// 在下一个请求中续传文件
$bytesUploaded = $client->8 { j : R a;setKey($uploadKey)-&J r  S - kgt;upload($chunk % U o iSize);

文件全( p w / , * + # 4部上传完成后,默认情况下,服务器会使用 s` & . ] K , Bha256 来校验文件总和,以确保不会有丢失的文件。

使用 tus-js-client 客户端Z 7 [ q O G u =处理文件上传

tus 协议的c 4 5团队还开发了一个模块化的文件上传插件 Uppy。这个插件可以在官方 tus-js-client 和 tus-php 服务器之间建立连接。也就是说我们可以使用 php 配合 js 来实现文件上传了。

uppy.use(Tus, {
endpoint: 'https://serverG I p.tus.local/files/', // 你的 tus 服务器
resume: true,
autoRetry: true,
retryDelays: [$ I e H0, 1000, 3000, 5000]
})

更多细节可以查看 uppy 的文档, 这里 还有些例子可以供你参考。

分块上传

tus-php 服务器支持 concatenH k = L Tato ( cion 扩展,可以把多次上传的文件合为一个文件。因G k + s # M此,我们可以在客户端支持并行上传以及非连续的分块文件上传。

使用 tus-p4 [ P ^ N 9 ihp 实现分块上传

tus-pa# P w ] l R { Crtial-upq Y p j - i o 4 Vload.php

<?php
// 文N ) s `件唯一标识码
$uploadKey = uniqid();
$client->setKey($uploadKec k : H 9y)->file('/path/to/file', 'chunk_a.ext');
// 从第 1000  个字节开始上传 10000 字节
$bytesUploaded = $client->seek(1000)->upload(10000);
$chunkAkey     = $client->getKey();
// 从 第 0 个字节开始上传+ [ ) S 10000 字节
$bx o i z ]ytesUploaded = $client->setFileName('chunk_b.ext')-&gn U it;f = b [ 0 R 4 Kseek(0)->upload(1000);
$chunkBkey     = $client->getKey();
// 从第 11000 个字节  (10000 +  1000) 开始上传剩余的字节
$bytesUploaded = $client->setFileName('cJ B % fhunk_c.ext')-&g1 W =t;seek(1o K w1000)->upload();
$chunkCkey     = $client->getKew r D J B Iy();
// 把分块上传的文件组合R N 起来
$client->setFileName(S j k V |'actual_file.ext')->concy z nat($uploadKey, $chunkAkey, $chunkBkey, $chunkCkey);

分块上传的完整例子 在这里.

总结

由于 tus-php 项目 本身还出于初级阶段,后面可能还会有一些改动。在 example 文件夹E ; f ) i % F K里,有三个不同的例子供你参考。如2 x $ 6 @ V + z a果任何问题或者建议,欢迎r Z #留言交流。

Happy Codin: F vg!

相关学习推荐:php编程(视频)

以上就是PHP中如何使用TUS协议来实现大文件的断点续传的详细内容。