コード例 #1
0
ファイル: byteserve.php プロジェクト: nrueckmann/yeager
function byteserve($filename, $mimeType = 'application/pdf')
{
    /*
    Byteserves the file $filename.
    
    When there is a request for a single range, the content is transmitted
    with a Content-Range header, and a Content-Length header showing the number
    of bytes actually transferred.
    
    When there is a request for multiple ranges, these are transmitted as a
    multipart message. The multipart media type used for this purpose is
    "multipart/byteranges".
    */
    $filesize = filesize($filename);
    $file = fopen($filename, "rb");
    $ranges = NULL;
    if ($_SERVER['REQUEST_METHOD'] == 'GET' && isset($_SERVER['HTTP_RANGE']) && ($range = stristr(trim($_SERVER['HTTP_RANGE']), 'bytes='))) {
        $range = substr($range, 6);
        $boundary = 'g45d64df96bmdf4sdgh45hf5';
        //set a random boundary
        $ranges = explode(',', $range);
    }
    if ($ranges && count($ranges)) {
        header("HTTP/1.1 206 Partial content");
        header("Accept-Ranges: bytes");
        if (count($ranges) > 1) {
            /*
            More than one range is requested.
            */
            //compute content length
            $content_length = 0;
            foreach ($ranges as $range) {
                set_range($range, $filesize, $first, $last);
                $content_length += strlen("\r\n--{$boundary}\r\n");
                $content_length += strlen("Content-type: " . $mimeType . "\r\n");
                $content_length += strlen("Content-range: bytes {$first}-{$last}/{$filesize}\r\n\r\n");
                $content_length += $last - $first + 1;
            }
            $content_length += strlen("\r\n--{$boundary}--\r\n");
            //output headers
            header("Content-Length: {$content_length}");
            //see http://httpd.apache.org/docs/misc/known_client_problems.html for an discussion of x-byteranges vs. byteranges
            header("Content-Type: multipart/x-byteranges; boundary={$boundary}");
            //output the content
            foreach ($ranges as $range) {
                set_range($range, $filesize, $first, $last);
                echo "\r\n--{$boundary}\r\n";
                echo "Content-type: " . $mimeType . "\r\n";
                echo "Content-range: bytes {$first}-{$last}/{$filesize}\r\n\r\n";
                fseek($file, $first);
                buffered_read($file, $last - $first + 1);
            }
            echo "\r\n--{$boundary}--\r\n";
        } else {
            /*
            A single range is requested.
            */
            $range = $ranges[0];
            set_range($range, $filesize, $first, $last);
            header("Content-Length: " . ($last - $first + 1));
            header("Content-Range: bytes {$first}-{$last}/{$filesize}");
            header("Content-Type: " . $mimeType);
            fseek($file, $first);
            buffered_read($file, $last - $first + 1);
        }
    } else {
        //no byteserving
        while (ob_get_level()) {
            ob_end_clean();
        }
        header("Accept-Ranges: bytes");
        header("Content-Length: {$filesize}");
        header("Content-Type: " . $mimeType);
        ob_end_flush();
        readfile($filename);
    }
    fclose($file);
}
コード例 #2
0
ファイル: serveFiles.php プロジェクト: skushch/igv.js
function byteserve($filename)
{
    /*
    Byteserves the file $filename.  
    
    When there is a request for a single range, the content is transmitted 
    with a Content-Range header, and a Content-Length header showing the number 
    of bytes actually transferred.
    
    When there is a request for multiple ranges, these are transmitted as a 
    multipart message. The multipart media type used for this purpose is 
    "multipart/byteranges".
    */
    global $MAX_FILE_SIZE;
    $filesize = filesize($filename);
    $ranges = NULL;
    if ($_SERVER['REQUEST_METHOD'] == 'GET' && isset($_SERVER['HTTP_RANGE']) && ($range = stristr(trim($_SERVER['HTTP_RANGE']), 'bytes='))) {
        $range = substr($range, 6);
        $ranges = explode(',', $range);
    }
    //If we don't find it in the header, check the query parameter
    if ($range == NULL && $ranges == NULL) {
        $strfirst = $_GET['start'];
        $last = $_GET['end'];
        $hasQueryStart = $strfirst != NULL;
        if ($hasQueryStart) {
            $first = (int) $strfirst;
            $last = (int) $last;
        }
    }
    if ($ranges && count($ranges) || $hasQueryStart) {
        header("HTTP/1.1 206 Partial content", True, 206);
        header("Accept-Ranges: bytes");
        if (count($ranges) > 1) {
            //unsatisfiable range
            header("HTTP/1.1 501 Do not support multiple ranges", True, 501);
        } else {
            //A single range is requested.
            $range = $ranges[0];
            if ($hasQueryStart) {
                //Nothing to do, $first and last already set
            } else {
                set_range($range, $filesize, $first, $last);
            }
            header("Content-Length: " . ($last - $first + 1));
            $contRange = "Content-Range: bytes {$first}-{$last}/{$filesize}";
            //log_message($contRange);
            header($contRange);
            $file = fopen($filename, "rb");
            fseek($file, $first);
            buffered_read($file, $last - $first + 1, 1024);
            fclose($file);
        }
    } else {
        $isHead = $_SERVER['REQUEST_METHOD'] == 'HEAD';
        header("Accept-Ranges: bytes");
        header("Content-Length: {$filesize}");
        if (!$isHead) {
            readfile($filename);
        }
    }
}