'Method not allowed']); exit; } if (empty($_FILES['file'])) { http_response_code(400); echo json_encode(['error' => 'No file']); exit; } $f = $_FILES['file']; if ($f['error'] !== UPLOAD_ERR_OK) { http_response_code(400); echo json_encode(['error' => 'Upload error: ' . $f['error']]); exit; } if ($f['size'] > $max_bytes) { http_response_code(413); echo json_encode(['error' => 'File too large (max 8 MB)']); exit; } $mime = mime_content_type($f['tmp_name']); if (!in_array($mime, $allowed_mime, true)) { http_response_code(415); echo json_encode(['error' => 'Only images (jpeg/png/gif/webp) allowed']); exit; } $ext_map = ['image/jpeg' => '.jpg', 'image/png' => '.png', 'image/gif' => '.gif', 'image/webp' => '.webp']; $ext = $ext_map[$mime] ?? '.jpg'; $dir = __DIR__ . '/images/'; if (!is_dir($dir)) { mkdir($dir, 0755, true); } $fname = round(microtime(true) * 1000) . $ext; $dest = $dir . $fname; if (!move_uploaded_file($f['tmp_name'], $dest)) { http_response_code(500); echo json_encode(['error' => 'Failed to save file']); exit; } echo json_encode(['url' => 'images/' . $fname]);