如何使用范围和刷新缓冲区页面逐块下载大文件块,以将下一个块与之前下载的块合并?

时间:2019-05-19 15:18:03

标签: php curl merge range chunks

我的服务器有客户端下载限制。我的服务器允许客户端下载少于4mb的文件。如果文件较大,则服务器终止下载过程。因此,我想使用范围来分割文件大小,逐块下载大文件。服务器不允许下载更大尺寸的文件,因此,当php代码在同一页面中输出所有块缓冲区时,服务器会捕获更大的文件。所以我想用3.999mb将缓冲区页面刷新3.999mb。每次将加载3.999mb缓冲区时,我将能够通过合并下载完整文件,然后再将块下载到新请求的下一个块中。

示例:

  

文件总大小为:10mb,现在我要开始下载第一个块   3.999mb,然后自动刷新带有新请求的页面,下一个3.999mb范围,该下一个范围将与第一个3.999mb合并,然后自动刷新,并显示下一个新请求   范围为2.2mb,并在下载7.998mb之前将其合并。下载总数   10mb(完整文件)。

     

注意:我不想使用javascript自动刷新(我的工作不支持javascript)。我想使用php   自动刷新到新的请求/加载下一个范围。

我尝试使用下面的代码来做到这一点,但是下面的代码只是下载了第一个块,并且在下载过程中不根据新请求刷新下一个范围。

<?php
session_start();
if (!isset($_SESSION['ranges'])) $_SESSION['ranges'] = 0;

    ini_set('max_execution_time', 0);

    $url  = $_GET['url'];

    $filesize = getSizeFile($url);
    $chunksize = (4*1024*1024)-1;
    $splits = range(0, $filesize, round($chunksize));

    $ranges = '';
    for($i = 0; $i<sizeof($splits); $i++)
    {
        $x = ($i == 0 ? 0 : $splits[$i]+1);
        $y = ($i == sizeof($splits)-1 ? $filesize : $splits[$i+1]);
        $ranges .= $x.'-'.$y.' ';
    }
    $range = explode(' ', $ranges);
    $size = ++$_SESSION['ranges'] % count($range)-1;

    $reloadRange = $range[$size];

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_USERAGENT, 'opera mini android');
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 0);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt ($ch, CURLOPT_HTTPHEADER, array(
        "HTTP/1.1 206 Partial Content",
        "Server: Apache",
        "Accept-Ranges: bytes",
        "Range: bytes= $reloadRange"
    ));

    $result = curl_exec($ch);
    $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $body = substr($result, $header_size);
    curl_close($ch);
    ob_start();
    echo $body;

    $b = ob_get_length();

    if(explode('-', $reloadRange)[0] == 0)
    {
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename='.basename($url)); 
        header('Content-Transfer-Encoding: binary');
        header('Connection: Keep-Alive');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
    }

    if(explode('-', $reloadRange)[1] !== getSizeFile($url))
    {
        if($b !== null)
        {
            header("Refresh: 0;");
            //header('Refresh: 0; url=/server/tt?url='.$url);
            exit();
        } else {
            exit;
        }
    } else {
        session_destroy();
        session_write_close();
        exit;
    }

function getSizeFile($url) { 
    if (substr($url,0,4)=='http') { 
        $x = array_change_key_case(get_headers($url, 1),CASE_LOWER); 
        if ( strcasecmp($x[0], 'HTTP/1.1 200 OK') != 0 ) { $x = $x['content-length'][1]; } 
        else { $x = $x['content-length']; } 
    } 
    else { $x = @filesize($url); } 

    return $x; 
} 

?>

谢谢

0 个答案:

没有答案