Resumable downloads when using PHP to send the file?

后端 未结 13 859
梦毁少年i
梦毁少年i 2020-11-22 12:22

We are using a PHP scripting for tunnelling file downloads, since we don\'t want to expose the absolute path of downloadable file:

header(\"Content-Type: $ct         


        
13条回答
  •  伪装坚强ぢ
    2020-11-22 13:08

    The top answer has various bugs.

    1. The major bug: It doesn't handle Range header correctly. bytes a-b should mean [a, b] instead of [a, b), and bytes a- is not handled.
    2. The minor bug: It doesn't use buffer to handle output. This may consume too much memory and cause low speed for large files.

    Here's my modified code:

    // TODO: configurations here
    $fileName = "File Name";
    $file = "File Path";
    $bufferSize = 2097152;
    
    $filesize = filesize($file);
    $offset = 0;
    $length = $filesize;
    if (isset($_SERVER['HTTP_RANGE'])) {
        // if the HTTP_RANGE header is set we're dealing with partial content
        // find the requested range
        // this might be too simplistic, apparently the client can request
        // multiple ranges, which can become pretty complex, so ignore it for now
        preg_match('/bytes=(\d+)-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches);
        $offset = intval($matches[1]);
        $end = $matches[2] || $matches[2] === '0' ? intval($matches[2]) : $filesize - 1;
        $length = $end + 1 - $offset;
        // output the right headers for partial content
        header('HTTP/1.1 206 Partial Content');
        header("Content-Range: bytes $offset-$end/$filesize");
    }
    // output the regular HTTP headers
    header('Content-Type: ' . mime_content_type($file));
    header("Content-Length: $filesize");
    header("Content-Disposition: attachment; filename=\"$fileName\"");
    header('Accept-Ranges: bytes');
    
    $file = fopen($file, 'r');
    // seek to the requested offset, this is 0 if it's not a partial content request
    fseek($file, $offset);
    // don't forget to send the data too
    ini_set('memory_limit', '-1');
    while ($length >= $bufferSize)
    {
        print(fread($file, $bufferSize));
        $length -= $bufferSize;
    }
    if ($length) print(fread($file, $length));
    fclose($file);
    

提交回复
热议问题