gpt4 book ai didi

php - 如何使用 PHP 下载大文件?

转载 作者:行者123 更新时间:2023-12-02 23:34:34 25 4
gpt4 key购买 nike

我花了一周的时间来找到这个问题的正确答案。 “正确”我的意思是绝对符合现有的网络标准,可靠且性能有效。最后,我找到了解决方案。

我在 StackOverflow ( Downloading large files reliably in PHP , How to download large files through PHP script ) 上找到的所有内容都不适用于我:

  • 两种解决方案都不支持范围请求。这使它们无法用于视频和音频流以及下载恢复;
  • 所有示例都与缓存和性能无关;

  • PHP 7.0 代码在 Chrome、Safari、Opera 和 Firefox 的桌面版本上进行了测试。维瓦尔第测试不成功。

    最佳答案

    const STDOUT_CHUNK_SIZE = 128 * 1024; // Buffer size to send data to browser. MUST be less then 1/3 of PHP memory size
    const CACHE_EXP_SEC = 1800; // Cache expire time is 30 min.

    $fileName = "large_video.mp4";
    $contentSize = filesize($fileName);
    $isAttachment = false; // false allows to use a file as inline element of web page

    // Parse range request. Browser asks for part of file
    if (isset($_SERVER["HTTP_RANGE"])) {
    list($units, $range) = explode("=", $_SERVER["HTTP_RANGE"], 2);
    if ($units !== "bytes") {
    http_response_code(416); // Requested Range Not Satisfiable
    exit;
    }
    $range = explode(",", $range, 2)[0]; // Get only first range. You can improve this ;)
    list($from, $to) = explode("-", $range, 2);
    $to = empty($to) ? ($contentSize - 1) : min(abs((int)$to), ($contentSize - 1));
    $from = (empty($from) || $to < abs((int)$from)) ? 0 : max(abs((int)$from), 0);
    }
    else {
    // Request for whole content
    $from = 0;
    $to = $contentSize - 1;
    }

    // Set response headers
    if ($from > 0 || $to < ($contentSize - 1))
    {
    http_response_code(206); // Partial Content
    header("Content-Type: video/mp4"));
    header("Content-Range: bytes $from-$to/$contentSize");
    header("Content-Length: " . ($from - $to + 1));
    }
    else {
    $etag = md5($file); // Content is immutable but file name can be changed
    if (isset($_SERVER["HTTP_IF_NONE_MATCH"]) && trim($_SERVER["HTTP_IF_NONE_MATCH"]) === $etag) {
    http_response_code(304); // Not Modified
    setCacheHeaders($etag);
    exit;
    }

    http_response_code(200); // Ok
    header("Content-Type: video/mp4"));
    header("Content-Length: $contentSize");
    if ($isAttachment) header("Content-Disposition: attachment; filename=\"$fileName\"");
    else header("Content-Disposition: inline");

    header("Accept-Ranges: bytes");
    setCacheHeaders($etag);
    }

    // Send response to client
    if ($file = fopen($fileName, "rb")) {
    fseek($file, $from);
    $counter = $from;
    set_time_limit(0);
    while (!feof($file) && $counter <= $to) {
    $bytesToRead = STDOUT_CHUNK_SIZE;
    if ($counter + $bytesToRead > $to) $bytesToRead = $to - $counter + 1;
    $data = fread($file, $bytesToRead);
    $counter += $bytesToRead;
    echo $data;
    flush();
    }
    fclose($file);

    function setCacheHeaders(string $etag, bool $cacheEnabled = true, bool $public = true)
    {
    if ($cacheEnabled) {
    header("ETag: $etag");
    $scope = $public ? "public" : "private";
    $sec = CACHE_EXP_SEC;
    $age = ($sec >= 0) ? ", max-age=$sec, s-maxage=$sec" : "";
    header("Cache-Control: $scope$age, no-transform");
    }
    else header("Cache-Control: no-cache, no-store, must-revalidate");
    }

    关于php - 如何使用 PHP 下载大文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47827768/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com