📤 PHP File Uploading: Your Digital Mailbox
Imagine this: You have a magical mailbox at home. People can send you letters, photos, and small packages. But you’re smart—you check every package before letting it inside. Is it too big? Is it something dangerous? You decide what comes in!
That’s exactly what file uploading in PHP does. Your website becomes the mailbox, and users send files through it. Let’s learn how to build a safe, smart mailbox!
🎯 What We’ll Learn
graph TD A["📤 File Uploading"] --> B["Basic Upload"] A --> C["Upload Validation"] A --> D["Upload Security"] B --> B1["HTML Form"] B --> B2["PHP Handler"] C --> C1["Size Check"] C --> C2["Type Check"] D --> D1["Safe Names"] D --> D2["Safe Location"]
📬 Part 1: Basic File Uploading
The Two-Part Magic Trick
Think of file uploading like sending a letter:
- The Envelope = HTML Form (where you put the file)
- The Postman = PHP Script (delivers it to your server)
Step 1: Create the Envelope (HTML Form)
<form action="upload.php"
method="POST"
enctype="multipart/form-data">
<input type="file" name="myFile">
<button type="submit">Send!</button>
</form>
Three magic words to remember:
| Part | Why It Matters |
|---|---|
method="POST" |
Sends file data safely |
enctype="multipart/form-data" |
Allows file to travel |
type="file" |
Creates the “attach” button |
⚠️ Without
enctype="multipart/form-data", your file goes nowhere! It’s like trying to mail a package without a stamp.
Step 2: The Postman Receives It (PHP)
<?php
// The file info lives in $_FILES
$file = $_FILES['myFile'];
// Where is it temporarily stored?
$tempPath = $file['tmp_name'];
// What's the original filename?
$fileName = $file['name'];
// How big is it (in bytes)?
$fileSize = $file['size'];
// Move it to your folder
move_uploaded_file(
$tempPath,
"uploads/" . $fileName
);
?>
🎁 What’s Inside $_FILES?
When someone uploads a file, PHP creates a gift box called $_FILES:
$_FILES['myFile'] = [
'name' => 'cute_cat.jpg' // Original name
'type' => 'image/jpeg' // What kind of file
'tmp_name' => '/tmp/php123' // Temporary home
'error' => 0 // Any problems?
'size' => 12345 // Size in bytes
]
🎯 Think of
tmp_nameas a waiting room. The file sits there until you decide to let it in or throw it away!
✅ Part 2: Upload Validation
Why Validate? A Story…
Imagine your mailbox accepts everything. One day, someone sends you a box that’s 10 feet tall! It won’t fit. Another time, someone sends a live snake! Dangerous!
Validation = Checking packages before accepting them.
Check 1: Was There an Error?
<?php
$file = $_FILES['myFile'];
// Error codes: 0 = success!
if ($file['error'] !== 0) {
echo "Upload failed!";
exit;
}
echo "File received safely!";
?>
Common error codes:
| Code | Meaning |
|---|---|
0 |
✅ All good! |
1 |
📏 File too big (server limit) |
2 |
📏 File too big (form limit) |
4 |
📭 No file was sent |
Check 2: Is It the Right Size?
<?php
$maxSize = 2 * 1024 * 1024; // 2MB
if ($file['size'] > $maxSize) {
echo "File too big! Max is 2MB.";
exit;
}
echo "Size is perfect!";
?>
🧮 Size Math: 1 MB = 1024 × 1024 bytes = 1,048,576 bytes
Check 3: Is It the Right Type?
<?php
$allowedTypes = [
'image/jpeg',
'image/png',
'image/gif'
];
$fileType = $file['type'];
if (!in_array($fileType, $allowedTypes)) {
echo "Only images allowed!";
exit;
}
echo "Nice image!";
?>
🔍 Better Type Checking (Don’t Trust Users!)
The type from $_FILES can be faked! Use this instead:
<?php
// Check the REAL file type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$realType = finfo_file(
$finfo,
$file['tmp_name']
);
finfo_close($finfo);
echo "Real type: " . $realType;
?>
🛡️ Part 3: Upload Security
The Danger Zone
🚨 Scary Story: A hacker uploads a file called
hack.php. If your server runs it… they control your website!
Security Rule 1: Never Trust the Filename
<?php
// BAD - User controls the name!
$badName = $file['name'];
// GOOD - Create a safe, random name
$safeExtension = pathinfo(
$file['name'],
PATHINFO_EXTENSION
);
$safeName = bin2hex(random_bytes(16));
$finalName = $safeName . '.' . $safeExtension;
// Result: "a1b2c3d4e5f6..." instead of "hack.php"
?>
Security Rule 2: Validate Extensions Too
<?php
$allowedExt = ['jpg', 'jpeg', 'png', 'gif'];
$extension = strtolower(
pathinfo($file['name'], PATHINFO_EXTENSION)
);
if (!in_array($extension, $allowedExt)) {
echo "Nice try! Only images.";
exit;
}
?>
Security Rule 3: Store Outside Web Root
graph TD A["Your Website"] --> B["/public_html/"] A --> C["/private/uploads/"] B --> D["❌ Hackers can access"] C --> E["✅ Safe from hackers"]
<?php
// Store files OUTSIDE public folder
$uploadDir = '/home/user/private/uploads/';
// NOT in /public_html/uploads/
move_uploaded_file(
$file['tmp_name'],
$uploadDir . $safeName
);
?>
Security Rule 4: Set Proper Permissions
<?php
// After moving the file
chmod($uploadDir . $safeName, 0644);
// 0644 means:
// Owner: read + write
// Others: read only
// No one can execute it!
?>
🏆 Complete Safe Upload Script
Here’s everything together:
<?php
function safeUpload($inputName, $uploadDir) {
// Step 1: Check if file exists
if (!isset($_FILES[$inputName])) {
return ['error' => 'No file sent'];
}
$file = $_FILES[$inputName];
// Step 2: Check for errors
if ($file['error'] !== 0) {
return ['error' => 'Upload failed'];
}
// Step 3: Check size (2MB max)
$maxSize = 2 * 1024 * 1024;
if ($file['size'] > $maxSize) {
return ['error' => 'File too big'];
}
// Step 4: Check real file type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$realType = finfo_file($finfo, $file['tmp_name']);
finfo_close($finfo);
$allowed = ['image/jpeg', 'image/png'];
if (!in_array($realType, $allowed)) {
return ['error' => 'Invalid file type'];
}
// Step 5: Create safe filename
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
$safeName = bin2hex(random_bytes(16)) . '.' . $ext;
// Step 6: Move to safe location
$destination = $uploadDir . $safeName;
if (move_uploaded_file($file['tmp_name'], $destination)) {
chmod($destination, 0644);
return ['success' => $safeName];
}
return ['error' => 'Move failed'];
}
// Use it!
$result = safeUpload('myFile', '/safe/uploads/');
print_r($result);
?>
📝 Quick Summary
| Step | What to Do | Why |
|---|---|---|
| 1 | Use enctype="multipart/form-data" |
Allows file upload |
| 2 | Check $_FILES['name']['error'] |
Catch problems early |
| 3 | Validate file size | Prevent huge files |
| 4 | Check REAL MIME type with finfo |
Don’t trust user data |
| 5 | Generate random filename | Prevent hack attempts |
| 6 | Store outside web root | Keep files unreachable |
| 7 | Set permissions to 0644 | No execution allowed |
🎉 You Did It!
You now know how to:
- ✅ Create upload forms
- ✅ Handle files with PHP
- ✅ Validate size and type
- ✅ Secure your uploads from hackers
🏠 Remember: Your website is your home. Every file upload is a visitor knocking at the door. Check who it is, what they’re carrying, and where they should go. Be a smart homeowner!
Next up: Try building your own image gallery with safe uploads! 🖼️
