Last updated: August 28, 2026.
A safe upload handler distrusts the browser-supplied filename and MIME type. Check the upload error, enforce a size limit, inspect the real file type, and create a server-side filename.
Validate and move the upload
<?php
$file = $_FILES['document'] ?? null;
if (!$file || $file['error'] !== UPLOAD_ERR_OK) throw new RuntimeException('Upload failed.');
if ($file['size'] > 5 * 1024 * 1024) throw new RuntimeException('File is too large.');
$mime = (new finfo(FILEINFO_MIME_TYPE))->file($file['tmp_name']);
$allowed = ['image/jpeg' => 'jpg', 'image/png' => 'png', 'application/pdf' => 'pdf'];
if (!isset($allowed[$mime])) throw new RuntimeException('Unsupported type.');
$name = bin2hex(random_bytes(16)) . '.' . $allowed[$mime];
if (!move_uploaded_file($file['tmp_name'], dirname(__DIR__) . '/private-uploads/' . $name)) throw new RuntimeException('Storage failed.');Apply defense in depth
- Keep uploads outside executable web directories.
- Serve private downloads through authorization.
- Escape the original filename before display.
- Limit image dimensions as well as byte size.
- Scan risky documents when malware scanning is available.
Building a database application with uploads?
PHPRunner can generate upload fields and file-management pages connected to your data. Explore PHPRunner.
Reference: PHP file upload documentation.