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

lllpaw

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

5062 1 1
1个回答

walkor

这有个例子,摘自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) . ' ' . _date_default_timezone_get_() : '';
    if (!empty($_SERVER) && $info) {
        _// Http 304.
        _if ($modified_time === $_SERVER) {
            _// 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) ? $file_info : '';
    $file_name = isset($file_info) ? $file_info : '';
    $header = "HTTP/1.1 200 OK\r\n";
    //if (isset(self::_$mimeTypeMap_)) {
        //$header .= "Content-Type: " . self::_$mimeTypeMap_ . "\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();
}
年代过于久远,无法发表回答
🔝