Secure File Upload with PHP

Last updated: August 25, 2026.

A secure upload handler validates the request, enforces a server-side size limit, identifies the file from its contents, generates its own filename, and stores it where uploaded code cannot execute.

Upload form

<form action="upload.php" method="post" enctype="multipart/form-data">
  <label for="uploaded-file">Choose a JPEG or PNG image</label>
  <input id="uploaded-file" name="uploaded_file"
         type="file" accept="image/jpeg,image/png" required>
  <button type="submit">Upload</button>
</form>

The accept attribute improves the file picker but is not security validation. The server must enforce every rule.

Validate and store the upload

<?php
declare(strict_types=1);

$file = $_FILES['uploaded_file'] ?? null;

if (!is_array($file) || is_array($file['error'] ?? null)) {
    throw new RuntimeException('Invalid upload request.');
}

if ($file['error'] !== UPLOAD_ERR_OK) {
    throw new RuntimeException('Upload failed with code ' . $file['error']);
}

if ($file['size'] > 5_000_000) {
    throw new RuntimeException('The file is larger than 5 MB.');
}

$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($file['tmp_name']);
$extensions = ['image/jpeg' => 'jpg', 'image/png' => 'png'];

if (!isset($extensions[$mime])) {
    throw new RuntimeException('Only JPEG and PNG images are accepted.');
}

$name = bin2hex(random_bytes(16)) . '.' . $extensions[$mime];
$uploadDirectory = dirname(__DIR__) . '/private-uploads';

if (!is_dir($uploadDirectory) || !is_writable($uploadDirectory)) {
    throw new RuntimeException('Upload storage is unavailable.');
}

if (!move_uploaded_file($file['tmp_name'], $uploadDirectory . '/' . $name)) {
    throw new RuntimeException('The uploaded file could not be stored.');
}

echo 'Upload completed.';

Production checklist

  • Require authentication and authorization before accepting a file.
  • Use CSRF protection for browser-based forms.
  • Store files outside the public web root or serve them through a controlled download endpoint.
  • Set upload_max_filesize, post_max_size, request limits, and storage quotas.
  • Use generated names; keep the original name only as separately encoded metadata.
  • Scan risky document types and re-encode images when appropriate.

See PHP’s file-upload documentation for upload error codes and configuration details.

Need uploads inside a database application? PHPRunner can generate authenticated upload forms, validation, and database-backed file fields.

admin

admin

One thought on “Secure File Upload with PHP

Leave a Reply

Your email address will not be published.