>백엔드 개발 >PHP 튜토리얼 >서버 바운드 업로드의 실시간 파일 크기를 어떻게 얻을 수 있습니까?

서버 바운드 업로드의 실시간 파일 크기를 어떻게 얻을 수 있습니까?

Susan Sarandon
Susan Sarandon원래의
2024-10-20 22:02:02296검색

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. 오류 처리 및 더 나은 성능을 위해 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.