Php Upload
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
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