Файловый менеджер - Редактировать - /home/skymarketplace/public_html/core/ImageServer.php
Назад
<?php class ImageServer { private string $uploadDir = __DIR__ . '/../uploads/'; private string $cacheDir = __DIR__ . '/../cache/'; private array $allowedTypes = ['image/jpeg', 'image/png', 'image/webp']; private int $maxWidth = 1024; private int $maxHeight = 1024; private int $rateLimit = 100; // max requests per IP per hour public function __construct() { if (!is_dir($this->cacheDir)) { mkdir($this->cacheDir, 0777, true); } } public function serve(string $filename): void { if (!$this->checkRateLimit()) { http_response_code(429); echo json_encode(['error' => 'Rate limit exceeded']); return; } $safeFilename = basename($filename); $filepath = realpath($this->uploadDir . $safeFilename); if (!$filepath || !file_exists($filepath)) { $fallbackPath = realpath(__DIR__ . '/' . $filename); if (!$fallbackPath || !file_exists($fallbackPath)) { $this->send404("Image not found"); return; } $filepath = $fallbackPath; } $mime = mime_content_type($filepath); if (!in_array($mime, $this->allowedTypes)) { $this->send404("Invalid image type"); return; } header("Cache-Control: public, max-age=31536000"); header("Expires: " . gmdate("D, d M Y H:i:s", time() + 31536000) . " GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s", filemtime($filepath)) . " GMT"); header("Content-Type: $mime"); [$width, $height] = getimagesize($filepath); if ($width > $this->maxWidth || $height > $this->maxHeight) { $this->resizeAndCache($filepath, $mime); } else { readfile($filepath); } } private function resizeAndCache(string $path, string $mime): void { $hash = md5($path . $this->maxWidth . $this->maxHeight); $cachePath = $this->cacheDir . $hash . '.webp'; if (file_exists($cachePath)) { header('Content-Type: image/webp'); readfile($cachePath); return; } [$srcWidth, $srcHeight] = getimagesize($path); $ratio = min($this->maxWidth / $srcWidth, $this->maxHeight / $srcHeight); $newWidth = (int)($srcWidth * $ratio); $newHeight = (int)($srcHeight * $ratio); $srcImage = match ($mime) { 'image/jpeg' => imagecreatefromjpeg($path), 'image/png' => imagecreatefrompng($path), 'image/webp' => imagecreatefromwebp($path), default => null }; if (!$srcImage) { $this->send404("Unsupported image"); return; } $dstImage = imagecreatetruecolor($newWidth, $newHeight); imagecopyresampled($dstImage, $srcImage, 0, 0, 0, 0, $newWidth, $newHeight, $srcWidth, $srcHeight); imagewebp($dstImage, $cachePath, 75); header('Content-Type: image/webp'); readfile($cachePath); imagedestroy($srcImage); imagedestroy($dstImage); } private function checkRateLimit(): bool { $ip = $_SERVER['REMOTE_ADDR']; $limitFile = sys_get_temp_dir() . "/img_rate_" . md5($ip) . ".json"; $limitData = file_exists($limitFile) ? json_decode(file_get_contents($limitFile), true) : ['count' => 0, 'time' => time()]; $now = time(); if ($now - $limitData['time'] > 3600) { $limitData = ['count' => 1, 'time' => $now]; } elseif ($limitData['count'] < $this->rateLimit) { $limitData['count']++; } else { return false; } file_put_contents($limitFile, json_encode($limitData)); return true; } private function send404(string $msg = "Not Found"): void { http_response_code(404); echo json_encode(['error' => $msg]); exit; } }
| ver. 1.4 |
Github
|
.
| PHP 8.1.31 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка