Как загрузить большой кусок файла по фрагменту, используя диапазон и обновить страницу буфера, чтобы объединить следующий фрагмент с ранее загруженным фрагментом? - PullRequest
0 голосов
/ 19 мая 2019

Мой сервер имеет ограничение загрузки клиента. Мой сервер позволяет клиенту загружать менее 4 Мб файла. Если размер файла больше, то процесс загрузки уничтожается сервером. Поэтому я хотел загрузить большой кусок файла по частям, используя диапазон, чтобы разделить размеры файлов. Сервер не допускает загрузку файлов большего размера, поэтому, когда php-код выводит все буферы чанков на той же странице, сервер перехватывает больший файл. Поэтому я хотел обновить страницу буфера 3.999mb на 3.999mb. Каждый раз, когда будет загружен буфер 3,999 Мб, и я смогу загрузить весь файл путем слияния перед загрузкой фрагмента в новый запрос следующего фрагмента.

Пример:

общий размер файла: 10 МБ, теперь я хочу начать загрузку с первого блока 3.999 МБ, затем автоматически обновляется страница с новым запросом в следующем диапазоне 3.999 МБ, и этот следующий диапазон будет объединяться с первыми 3.999 МБ, а затем автоматически обновляться с новым запросом в следующем диапазон 2.2mb и объединить его перед загрузкой 7.998mb. Всего скачано 10 МБ (полный файл).

NB. Я не хочу использовать 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; 
} 

?>

Спасибо

...