stat($filePath)['size']; if (isset($_GET['stream'])) { session_write_close(); while (ob_get_level()) { ob_end_clean(); } if (ini_get('zlib.output_compression')) { ini_set('zlib.output_compression', 'Off'); } $start = 0; $end = $fileSize - 1; $length = $fileSize; if (isset($_SERVER['HTTP_RANGE'])) { $rangeHeader = $_SERVER['HTTP_RANGE']; $matches = []; if (preg_match('/bytes=(\d+)-(\d*)/', $rangeHeader, $matches)) { $start = intval($matches[1]); if (!empty($matches[2])) { $end = intval($matches[2]); } $length = $end - $start + 1; header('HTTP/1.1 206 Partial Content'); header('Content-Range: bytes ' . $start . '-' . $end . '/' . $fileSize); } } header('Content-Type: application/pdf'); header('Content-Disposition: inline; filename="' . basename($filePath) . '"'); header("Accept-Ranges: bytes"); header("Content-Length: $length"); header("Cache-Control: no-cache, no-store, must-revalidate"); header("Pragma: no-cache"); header("Expires: 0"); set_time_limit(0); $minChunkSize = 64 * 1024; // 64KB minimum $maxChunkSize = 2 * 1024 * 1024; // 2MB maximum $chunkSize = 256 * 1024; // Start with 256KB $currentPosition = $start; $bytesRemaining = $length; $lastChunkTime = microtime(true); try { while ($bytesRemaining > 0) { if (connection_aborted()) { break; } $readSize = min($chunkSize, $bytesRemaining); $chunkData = $sftp->get($filePath, false, $currentPosition, $readSize); if ($chunkData !== false) { $bytesSent = strlen($chunkData); echo $chunkData; $bytesRemaining -= $bytesSent; $currentPosition += $bytesSent; if (ob_get_level()) { ob_flush(); } flush(); $currentTime = microtime(true); $timeDiff = $currentTime - $lastChunkTime; $lastChunkTime = $currentTime; if ($timeDiff > 0) { $speed = $bytesSent / $timeDiff; $chunkSize = min( max($minChunkSize, $chunkSize * (($speed > 512 * 1024) ? 1.5 : 0.8)), $maxChunkSize ); } } else { break; } } } catch (Exception $e) { error_log("Streaming error: " . $e->getMessage()); } exit; } ?>