如何取得伺服器綁定上傳的即時檔案大小?

Susan Sarandon
發布: 2024-10-20 22:02:02
原創
274 人瀏覽過

How Can I Get the Real-Time File Size of a Server-Bound Upload?

問題:

在不阻塞伺服器的情況下,取得上傳檔案寫入伺服器的即時檔案大小和用戶端。

上下文:

使用帶有文件或 Blob 正文的 fetch() 的 POST 請求寫入伺服器時,客戶端瀏覽器中的文件上傳進度。

要求:

在將檔案大小寫入伺服器檔案系統時將其顯示為文字/事件流。當檔案上傳期間作為查詢字串參數提供的所有位元組都已寫入時停止。目前從單獨的腳本檢索檔案大小,該腳本在檔案寫入伺服器後調用。

實作:

最初嘗試使用 PHP 但遇到了問題由於未定義的 HTTP_LAST_EVENT_ID 和報告的檔案大小不正確而導致的錯誤。也嘗試了不同的方法和語言,如 bash、c、nodejs 和 python。

解決方案:

  1. 清除檔案統計快取以取得即時檔案大小:
<code class="php">clearstatcache(true, $upload);
$data = filesize($upload);</code>
登入後複製
    修改
  1. 修改
  2. 修改
修改
<code class="php">// Check if the header's been sent to avoid `PHP Notice:  Undefined index: HTTP_LAST_EVENT_ID in stream.php on line `
// php 7+
//$lastId = $_SERVER["HTTP_LAST_EVENT_ID"] ?? 0;
// php < 7
$lastId = isset($_SERVER["HTTP_LAST_EVENT_ID"]) ? intval($_SERVER["HTTP_LAST_EVENT_ID"]) : 0;

$upload = $_GET["filename"];
$data = 0;
// if file already exists, its initial size can be bigger than the new one, so we need to ignore it
$wasLess = $lastId != 0;
while ($data < $_GET["filesize"] || !$wasLess) {
    // system calls are expensive and are being cached with assumption that in most cases file stats do not change often
    // so we clear cache to get most up to date data
    clearstatcache(true, $upload);
    $data = filesize($upload);
    $wasLess |= $data < $_GET["filesize"];
    // don't send stale filesize
    if ($wasLess) {
        sendMessage($lastId, $data);
        $lastId++;
    }
    // not necessary here, though without thousands of `message` events will be dispatched
    //sleep(1);
    // millions on poor connection and large files. 1 second might be too much, but 50 messages a second must be okay
    usleep(20000);
}</code>
登入後複製
修改
    修改
  1. 修改
  2. 修改
  3. 修改
  4. 修改
修改
<code class="javascript">const [fileId, request, source] = [
    Math.random().toString(36).substr(2),
    new Request(`${url}?fileId=${fileId}&amp;size=${filesize}`, {
        method: "POST",
        headers: headers,
        body: file
    }),
    new EventSource(`${stream}?fileId=${fileId}`)
];</code>
登入後複製
修改
    修改
  1. 修改
  2. 修改
修改
<code class="php">function setUnique(string $id, int $size) {
    // implement with your storage of choice
}

function updateProgress(string $id, int $processed) {
    // implement with your storage of choice
}</code>
登入後複製
修改
    修改
  1. 修改
  2. 修改
修改
<code class="php">list($progress, $size) = getProgress($_GET["fileId"]);</code>
登入後複製
修改

修改修改修改

修改
    了stream.php,進行錯誤處理並使用usleep以獲得更好的性能:
  • 包含fileId和fileSize作為POST 請求的一部分,並使用redis 或memcache 添加內存儲存來儲存檔案元資料。
  • 在客戶端JavaScript 中利用EventSource:
根據您選擇的儲存機制自訂setUnique 和updateProgress 函數:從儲存中取得進度:重要提示:所提供的解決方案優先考慮功能而非安全性,不建議在不實施額外安全措施的情況下用於生產使用。 開啟的連線數可能需要根據伺服器配置和資源利用率進行調整。 可以考慮使用輪詢取代EventSource,以減少開啟連線數,但可能會影響回應能力。 usleep 中的最佳睡眠時間() 可能會有所不同,具體取決於所需的更新頻率和效能權衡。

以上是如何取得伺服器綁定上傳的即時檔案大小?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板