ホームページ >バックエンド開発 >PHPチュートリアル >サーバーバインドアップロードのリアルタイムファイルサイズを取得するにはどうすればよいですか?

サーバーバインドアップロードのリアルタイムファイルサイズを取得するにはどうすればよいですか?

Susan Sarandon
Susan Sarandonオリジナル
2024-10-20 22:02:02319ブラウズ

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

質問:

両方のサーバーをブロックせずに、アップロードされたファイルのサーバーへの書き込み中のファイル サイズをリアルタイムで取得します。

コンテキスト:

ファイルまたは Blob 本文を含む fetch() の POST リクエストを使用してサーバーに書き込む際の、クライアントのブラウザーでのファイル アップロードの進行状況。

要件:

サーバー ファイルシステムへの書き込み中のファイル サイズを text/event-stream として表示します。ファイルのアップロード中にクエリ文字列パラメータとして指定されたすべてのバイトが書き込まれたときに停止します。ファイル サイズは現在、ファイルがサーバーに書き込まれた後に呼び出される別のスクリプトから取得されます。

実装:

最初は PHP を使用して試みましたが、問題が発生しました。未定義の HT​​TP_LAST_EVENT_ID と誤ったファイル サイズが報告されることによるエラー。また、bash、c、nodejs、python などのさまざまなアプローチや言語も実験しました。

解決策:

  1. ファイル統計キャッシュをクリアして、リアルタイム ファイルを取得します。 size:
<code class="php">clearstatcache(true, $upload);
$data = filesize($upload);</code>
  1. パフォーマンスを向上させるためにエラー処理と usleep を使用することで stream.php を変更しました:
<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. fileId と fileSize を含めますPOST リクエストの一部として、ファイルのメタデータを保存するために Redis または memcache を使用してメモリ内ストレージを追加します。
  2. クライアント側 JavaScript で EventSource を利用します:
<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. 選択したストレージ メカニズムに基づいて setUnique 関数と updateProgress 関数をカスタマイズします:
<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. ストレージから進行状況を取得します:
<code class="php">list($progress, $size) = getProgress($_GET["fileId"]);</code>

重要な注意事項:

  • 提供されるソリューションはセキュリティよりも機能を優先するため、追加のセキュリティ対策を実装せずに運用環境で使用することはお勧めできません。
  • オープン接続の数は必要な場合があります。サーバー構成とリソース使用率に基づいて調整されます。
  • EventSource の代わりにポーリングを使用すると、開いている接続の数を減らすことができますが、応答性に影響を与える可能性があります。
  • usleep の最適なスリープ時間() は、希望する更新頻度とパフォーマンスのトレードオフによって異なる場合があります。

以上がサーバーバインドアップロードのリアルタイムファイルサイズを取得するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。