PHP 中使用 TUS 協定來實現大檔案的斷點續傳

藏色散人
發布: 2023-04-07 12:54:01
轉載
3052 人瀏覽過

你是否曾經為大檔案上傳而苦惱?如果檔案上傳的過程中,因為某些原因中斷了,是否可以從中斷的位置繼續上傳,而不用重新上傳整個檔案?如果你有這樣的困惑,那麼請繼續閱讀下面的內容。

在現代網站應用程式中,上傳檔案是非常常見的。在任何語言中,透過使用一些工具,都可以實現文件上傳的功能。但是,如果處理大檔案上傳的需求,還是有點麻煩的。

假如你此時正在上傳一個很大的文件,大約一個小時過去了,進度是 90%。突然斷網了或是瀏覽器崩潰了,上傳的程式退出,你要再全部重新來過。真的很不爽,對不對?還有更讓人鬱悶的是,如果你的網路速度很慢,那麼,無論你重來多少次,你都不可能上傳成功。

在 PHP 中,我們可以試著利用 tus 協定的斷點續傳功能來解決這個問題。

什麼是 tus?

Tus 是基於 HTTP 的  檔案斷點續傳開放式協定。斷點續傳的意思是不管是用戶自行中斷,還是因為網路等原因的意外中斷,都可以從中斷的地方繼續上傳,而不會重新開始。

Tus 協定是在 2017 年5月被​​ Vimeo 採用的。

為什麼用tus?

引用Vimeo 的部落格:

我們之所以決定用tus,是因為它能以簡潔開放的形式,將文件上傳的過程標準化。這種標準化有利於 API 的開發者更專注於應用程式本身的邏輯,而非檔案上傳的過程。

使用這種方式上傳的另一個好處是,你可以在筆記本上開始上傳文件,然後再轉到手機或其他裝置繼續上傳同一個文件,這可以極大地提升用戶體驗。

PHP 中使用 TUS 協定來實現大檔案的斷點續傳

圖片: Tus 大致的工作流程

#開始

第一步,載入依賴。

$ composer require ankitpokhrel/tus-php
登入後複製

tus-php 是用於 tus 斷點續傳協定 v1.0.0 的一個的純 PHP 框架,完美實現了 服務端與客戶端的互動 。

更新: 現在 Vimeo 官方 PHP 函式庫 的 v3 用的是 TusPHP

建立一個處理請求的服務端

你可以像下面這樣建立一個服務端.

// server.php
$server   = new \TusPhp\Tus\Server('redis');
$response = $server->serve();
$response->send();
exit(0); // 退出当前 PHP 进程
登入後複製

你需要設定你的伺服器以便能對特定的終端進行回應。如果使用Nginx 的話你可以像下面這樣配置:

# nginx.conf
location /files {
    try_files $uri $uri/ /path/to/server.php?$query_string;
}
登入後複製

假設我們服務端的URL 是http://server.tus.local. 因此,基於我們上面的Nginx 配置,我們可以透過http:// server.tus.local/files. 來存取到我們的tus 終端機.

基於RESTful 風格的端點配置:

# 获取有关服务器目前配置的信息\
OPTIONS /files
# 检查上传的文件是否合法\
HEAD /files/{upload-key}
# 创建\
POST /files
# 修改\
PATCH /files/{upload-key}
# 删除\
DELETE /files/{upload-key}
登入後複製

查看協定細則 取得更多關於路由的訊息。

如果你是用類似 Laravel 的框架,那麼你就不需要在設定檔裡定義這些了, 可以直接定義路由來存取 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>
登入後複製

提交表單後,我們需要按照幾個步驟來處理上傳。

建立一個 tus-php 用戶端物件

// Tus client
$client = new \TusPhp\Tus\Client(&#39;http://server.tus.local&#39;);
登入後複製

上面程式碼中的第一個參數是你的 tus 伺服器位址。

2. 使用檔案元資料初始化客戶端

為了確保上傳檔案的唯一性,我們需要給每個上傳的檔案以唯一標識。這樣在文件中斷後續傳的時候,伺服器就可以很清楚辨識出,哪幾個片段是屬於同一個文件得。這個標識碼可以自己指定,也可以由系統產生。

// 设置标识码和文件元数据
$client->setKey($uploadKey)
    ->file($_FILES[&#39;tus_file&#39;][&#39;tmp_name&#39;], &#39;your file name&#39;);
登入後複製

如果不想指定標識碼,可以這樣寫,由系統會自動產生:

$client->file($_FILES[&#39;tus_file&#39;][&#39;tmp_name&#39;], &#39;your file name&#39;);
$uploadKey = $client->getKey(); // Unique upload key
登入後複製

3. 分塊上傳檔案

// $chunkSize 是以字节为单位的,例如 5000000 等于 5 MB
$bytesUploaded = $client->upload($chunkSize);
登入後複製

當你想要續傳下一塊的時候,就可以帶同樣的識別碼參數來續傳。

// 在下一个请求中续传文件
$bytesUploaded = $client->setKey($uploadKey)->upload($chunkSize);
登入後複製

檔案全部上傳完成後,預設情況下,伺服器會使用 sha256 來校驗檔案總和,以確保不會有遺失的檔案。

使用 tus-js-client 用戶端處理檔案上傳

tus 協定的團隊也開發了一個模組化的檔案上傳外掛程式 Uppy。這個插件可以在官方 tus-js-client 和 tus-php 伺服器之間建立連接。也就是說我們可以使用 php 來配合 js 來實作檔案上傳了。

uppy.use(Tus, {
  endpoint: &#39;https://server.tus.local/files/&#39;, // 你的 tus 服务器
  resume: true,
  autoRetry: true,
  retryDelays: [0, 1000, 3000, 5000]
})
登入後複製

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

分块上传

tus-php 服务器支持 concatenation 扩展,可以把多次上传的文件合为一个文件。因此,我们可以在客户端支持并行上传以及非连续的分块文件上传。

使用 tus-php 实现分块上传

tus-partial-upload.php

<?php
// 文件唯一标识码
$uploadKey = uniqid();
$client->setKey($uploadKey)->file(&#39;/path/to/file&#39;, &#39;chunk_a.ext&#39;);
// 从第 1000  个字节开始上传 10000 字节
$bytesUploaded = $client->seek(1000)->upload(10000);
$chunkAkey     = $client->getKey();
// 从 第 0 个字节开始上传 10000 字节
$bytesUploaded = $client->setFileName(&#39;chunk_b.ext&#39;)->seek(0)->upload(1000);
$chunkBkey     = $client->getKey();
// 从第 11000 个字节  (10000 +  1000) 开始上传剩余的字节
$bytesUploaded = $client->setFileName(&#39;chunk_c.ext&#39;)->seek(11000)->upload();
$chunkCkey     = $client->getKey();
// 把分块上传的文件组合起来
$client->setFileName(&#39;actual_file.ext&#39;)->concat($uploadKey, $chunkAkey, $chunkBkey, $chunkCkey);
登入後複製

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

总结

由于 tus-php 项目 本身还出于初级阶段,后面可能还会有一些改动。在 example 文件夹里,有三个不同的例子供你参考。如果任何问题或者建议,欢迎留言交流。

以上是PHP 中使用 TUS 協定來實現大檔案的斷點續傳的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
php
來源:learnku.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!