Skip to main content
File Uploading

File Uploading

Uploads combine file handling with security. Validate the file type and size, generate a new name, and decide whether the file should be publicly reachable.

The form

<form method="post" action="<?= site_url('files/upload') ?>" enctype="multipart/form-data">
    <input type="hidden" name="<?= csrf_token() ?>" value="<?= csrf_hash() ?>">
    <input type="file" name="document" accept=".pdf,.png,.jpg,.jpeg,.webp">
    <button type="submit">Upload</button>
</form>

Validate and store

public function upload()
{
    $rules = [
        'document' => 'uploaded[document]|max_size[document,2048]|ext_in[document,pdf,png,jpg,jpeg,webp]|mime_in[document,application/pdf,image/png,image/jpeg,image/webp]',
    ];

    if (! $this->validate($rules)) {
        return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
    }

    $file = $this->request->getFile('document');
    if ($file === null || ! $file->isValid() || $file->hasMoved()) {
        return redirect()->back()->with('error', 'Upload failed.');
    }

    $name = $file->getRandomName();
    $file->move(WRITEPATH . 'uploads', $name);

    return redirect()->back()->with('success', 'File uploaded.');
}

Security rules

  • Never trust the client-provided extension or MIME type; validate both.
  • Generate a random filename and keep the original name in the database if you need to display it.
  • Store private files outside the web root and serve them through a controller that checks permission.
  • Limit the size and the number of files per request.
  • For images, verify them with getimagesize() and consider re-encoding to strip metadata and embedded payloads.
  • Set restrictive permissions on the upload directory and do not execute files from it.