Skip to content

Php Upload

DodaTech 5 min read

title: PHP File Upload — Complete Guide to Uploading Files Securely description: 'Learn PHP file upload: handling single and multiple files, validation, MIME types, size limits, secure storage, image processing, and error handling.' date: 2026-06-28 lastmod: 2026-06-28 weight: 40 tags: [backend, php]


PHP file upload enables users to upload images, documents, and other files through HTML forms, with proper validation, security checks, and storage management.

## What You'll Learn

By the end of this tutorial, you'll handle single and multiple file uploads, validate file types and sizes, store files securely, process images with GD/Imagick, and handle upload errors gracefully.

## Why File Upload Matters

File upload is a core feature of most web applications — profile pictures, document attachments, media galleries, CSV imports. Insecure uploads are a major attack vector.

## Real-World Use

A job portal allows applicants to upload resumes (PDF, DOCX) and profile photos. The app validates file types, compresses images, and stores files with randomized names outside the web root.

## Upload Learning Path

```mermaid
flowchart LR
  A[Forms] --> B[File Upload]
  B --> C[Security]
  C --> D[Email]
  D --> E[MVC]
  A --> F{You Are Here}
  style F fill:#f90,color:#fff

Upload Form

<?php
<!-- upload.php -->
<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="hidden" name="MAX_FILE_SIZE" value="5000000">
    <label>Select file:</label>
    <input type="file" name="uploadedFile">
    <input type="submit" value="Upload">
</form>

Single File Upload

<?php
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_FILES["uploadedFile"])) {
    $file = $_FILES["uploadedFile"];
    if ($file["error"] !== UPLOAD_ERR_OK) {
        die("Upload failed with error code: " . $file["error"]);
    }
    $allowedTypes = ["image/jpeg", "image/png", "application/pdf"];
    $maxSize = 5 * 1024 * 1024;  // 5MB
    if (!in_array($file["type"], $allowedTypes)) {
        die("Invalid file type: " . $file["type"]);
    }
    if ($file["size"] > $maxSize) {
        die("File too large. Maximum: 5MB");
    }
    $extension = pathinfo($file["name"], PATHINFO_EXTENSION);
    $newName = bin2hex(random_bytes(16)) . "." . $extension;
    $uploadDir = __DIR__ . "/uploads/";
    if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true);
    if (move_uploaded_file($file["tmp_name"], $uploadDir . $newName)) {
        echo "File uploaded successfully: " . $newName;
    } else {
        echo "Failed to move uploaded file";
    }
}

Multiple File Upload

<?php
<form action="/upload-multiple" method="post" enctype="multipart/form-data">
    <input type="file" name="files[]" multiple accept="image/*">
    <input type="submit" value="Upload All">
</form>
<?php
if (isset($_FILES["files"])) {
    foreach ($_FILES["files"]["name"] as $i => $name) {
        if ($_FILES["files"]["error"][$i] !== UPLOAD_ERR_OK) continue;
        $tmp = $_FILES["files"]["tmp_name"][$i];
        $ext = pathinfo($name, PATHINFO_EXTENSION);
        $newName = bin2hex(random_bytes(8)) . "." . $ext;
        move_uploaded_file($tmp, __DIR__ . "/uploads/" . $newName);
        echo "Uploaded: $name as $newName<br>";
    }
}

Image Processing with GD

<?php
function createThumbnail(string $sourcePath, string $destPath, int $maxWidth = 200): void {
    [$width, $height, $type] = getimagesize($sourcePath);
    $ratio = $maxWidth / $width;
    $newHeight = (int)($height * $ratio);
    $thumb = imagecreatetruecolor($maxWidth, $newHeight);
    $source = match($type) {
        IMAGETYPE_JPEG => imagecreatefromjpeg($sourcePath),
        IMAGETYPE_PNG => imagecreatefrompng($sourcePath),
        IMAGETYPE_GIF => imagecreatefromgif($sourcePath),
        default => throw new \InvalidArgumentException("Unsupported image type"),
    };
    imagecopyresampled($thumb, $source, 0, 0, 0, 0, $maxWidth, $newHeight, $width, $height);
    imagejpeg($thumb, $destPath, 85);
    imagedestroy($thumb);
    imagedestroy($source);
}

Error Handling

<?php
$errorMessages = [
    UPLOAD_ERR_INI_SIZE => "File exceeds php.ini upload_max_filesize",
    UPLOAD_ERR_FORM_SIZE => "File exceeds MAX_FILE_SIZE in form",
    UPLOAD_ERR_PARTIAL => "File only partially uploaded",
    UPLOAD_ERR_NO_FILE => "No file was selected",
    UPLOAD_ERR_NO_TMP_DIR => "Server missing temporary directory",
    UPLOAD_ERR_CANT_WRITE => "Failed to write file to disk",
    UPLOAD_ERR_EXTENSION => "PHP extension stopped the upload",
];
$errorCode = $_FILES["file"]["error"];
if ($errorCode !== UPLOAD_ERR_OK) {
    echo $errorMessages[$errorCode] ?? "Unknown error";
}

Common Mistakes

1. Trusting File Extension

File extensions are easily spoofed. Validate MIME type with finfo_open() and finfo_file().

2. Storing Files in Web Root

Files in web root can be accessed directly. Store uploaded files outside public_html with controlled access.

3. Using Original Filenames

Original filenames can contain path traversal characters. Generate randomized names using bin2hex(random_bytes()).

4. Not Setting File Size Limits

Unlimited uploads exhaust disk space. Set limits in php.ini (upload_max_filesize, post_max_size) and in code.

5. Allowing Dangerous File Types

Allowing PHP, EXE, or JS uploads can lead to RCE. Restrict to safe types like images, PDFs, and text files.

Practice Questions

1. What enctype is required for file upload forms?

enctype="multipart/form-data". The default application/x-www-form-urlencoded doesn't support binary files.

2. How do you validate the actual file type?

Use finfo_open(FILEINFO_MIME_TYPE) to detect the real MIME type from file content, not the filename extension.

3. Why use move_uploaded_file() instead of copy()?

move_uploaded_file() checks that the file was actually uploaded via HTTP POST, preventing local file inclusion attacks.

4. How do you handle large file uploads?

Set upload_max_filesize and post_max_size in php.ini. Use chunked uploads for very large files.

5. Challenge: Build a secure image upload handler that validates, creates thumbnails, and saves safely.

<?php
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_FILES["avatar"])) {
    $file = $_FILES["avatar"];
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mime = finfo_file($finfo, $file["tmp_name"]);
    finfo_close($finfo);
    if (!in_array($mime, ["image/jpeg", "image/png"])) die("Only JPEG/PNG allowed");
    if ($file["size"] > 2 * 1024 * 1024) die("Max 2MB");
    $newName = bin2hex(random_bytes(16)) . ".jpg";
    $path = __DIR__ . "/uploads/" . $newName;
    move_uploaded_file($file["tmp_name"], $path);
    createThumbnail($path, __DIR__ . "/thumbs/" . $newName, 150);
    echo "Avatar uploaded and thumbnail created";
}

FAQ

Can I upload files via AJAX?

Yes. Use FormData API with XMLHttpRequest or fetch. Set contentType and processData to false in jQuery.

What is the maximum upload file size in PHP?

Default is 2MB (upload_max_filesize = 2M). Change in php.ini or .htaccess. Also check post_max_size.

How do I resume interrupted uploads?

Implement chunked uploads on the client side, reassembling chunks on the server. Or use a library like Plupload.

What is the best directory structure for uploads?

Store outside web root: /var/uploads/. Serve through a PHP script that validates access before streaming.

How do I upload files to cloud storage (S3) instead of local disk?

Use the AWS SDK for PHP to upload directly to S3. Configure the bucket policy for public or signed URLs.

Mini Project: Document Upload System

Build a secure document upload system with type validation, size limits, and organized storage.

<?php
$uploadDir = __DIR__ . "/documents/";
$allowedTypes = ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"];
$maxSize = 10 * 1024 * 1024;
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_FILES["doc"])) {
    $file = $_FILES["doc"];
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mime = finfo_file($finfo, $file["tmp_name"]);
    finfo_close($finfo);
    if (!in_array($mime, $allowedTypes)) die("Only PDF and DOCX allowed");
    if ($file["size"] > $maxSize) die("Max 10MB");
    if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true);
    $newName = date("Ymd_") . bin2hex(random_bytes(8)) . "." . pathinfo($file["name"], PATHINFO_EXTENSION);
    move_uploaded_file($file["tmp_name"], $uploadDir . $newName);
    echo "Document saved as: $newName";
}

What's Next

PHP Email PHP Security PHP Performance

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro