private array $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif'];
private array $allowedMimes = ['image/jpeg', 'image/png', 'image/gif'];
private int $maxSize = 2 * 1024 * 1024; // 2 MB
private string $uploadDir = '/var/www/uploads/';
public function upload(array $file): string {
// 1. Sprawdz błędy uploadu
if ($file['error'] !== UPLOAD_ERR_OK) {
throw new Exception('Błąd uploadu: ' . $file['error']);
if ($file['size'] > $this->maxSize) {
throw new Exception('Plik za duży');
// 3. Walidacja rozszerzenia
$extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if (!in_array($extension, $this->allowedExtensions)) {
throw new Exception('Niedozwolone rozszerzenie');
// 4. Walidacja MIME (finfo)
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file($file['tmp_name']);
if (!in_array($mimeType, $this->allowedMimes)) {
throw new Exception('Niedozwolony typ pliku');
// 5. Generowanie bezpiecznej nazwy
$safeName = bin2hex(random_bytes(16)) . '.' . $extension;
$targetPath = $this->uploadDir . $safeName;
// 6. Przeniesienie pliku
if (!move_uploaded_file($file['tmp_name'], $targetPath)) {
throw new Exception('Nie udało się zapisać pliku');
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$uploader = new SecureUploader();
$filename = $uploader->upload($_FILES['userfile']);
echo "Zapisano jako: " . htmlspecialchars($filename);
echo "Błąd: " . htmlspecialchars($e->getMessage());