如何向http客户端发送大文件(几百兆 1个多G)?

如何向http客户发送几百兆 1G的大文件?PHP读取大文件一般采用每次读取一块字符串,至到文件结束。问题是向浏览器发送第一块后http协议就会关闭会话,后续块无法发送。
 
比如通过浏览器下载文件这种应用。
已邀请:

walkor

赞同来自: lllpaw

这有个例子,摘自workerman/WebServer.php里的一个发送文件的方法。
 
function sendFile($connection, $file_path)
{
    // Check 304.
    
$info = stat($file_path);
    $modified_time = $info ? date('D, d M Y H:i:s', $info['mtime']) . ' ' date_default_timezone_get() : '';
    if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $info) {
        // Http 304.
        
if ($modified_time === $_SERVER['HTTP_IF_MODIFIED_SINCE']) {
            // 304
            
Http::header('HTTP/1.1 304 Not Modified');
            // Send nothing but http headers..
            
$connection->close('');
            return;
        }
    }

    // Http header.
    
if ($modified_time) {
        $modified_time = "Last-Modified: $modified_time\r\n";
    }
    $file_size = filesize($file_path);
    $file_info = pathinfo($file_path);
    $extension = isset($file_info['extension']) ? $file_info['extension'] : '';
    $file_name = isset($file_info['filename']) ? $file_info['filename'] : '';
    $header = "HTTP/1.1 200 OK\r\n";
    //if (isset(self::$mimeTypeMap[$extension])) {
        //$header .= "Content-Type: " self::$mimeTypeMap[$extension] . "\r\n";
    //} else {
        $header .= "Content-Type: application/octet-stream\r\n";
        $header .= "Content-Disposition: attachment; filename=\"$file_name\"\r\n";
    //}
    $header .= "Connection: keep-alive\r\n";
    $header .= $modified_time;
    $header .= "Content-Length: $file_size\r\n\r\n";
    $trunk_limit_size = 1024*1024;
    if ($file_size < $trunk_limit_size) {
        return $connection->send($header.file_get_contents($file_path), true);
    }
    $connection->send($header, true);

    // Read file content from disk piece by piece and send to client.
    
$connection->fileHandler fopen($file_path, 'r');
    $do_write = function()use($connection)
    {
        // Send buffer not full.
        
while(empty($connection->bufferFull))
        {
            // Read from disk.
            
$buffer = fread($connection->fileHandler, 8192);
            // Read eof.
            
if($buffer === '' || $buffer === false)
            {
                return;
            }
            $connection->send($buffer, true);
        }
    };
    // Send buffer full.
    
$connection->onBufferFull function($connection)
    {
        $connection->bufferFull true;
    };
    // Send buffer drain.
    
$connection->onBufferDrain function($connection)use($do_write)
    {
        $connection->bufferFull false;
        $do_write();
    };
    $do_write();
}

要回复问题请先登录注册