<?php
// upload_simple.php
$uploadDir = __DIR__ . '/uploads';
$maxSize = 2 * 1024 * 1024; // 2MB
$allowedExt = ['jpg','jpeg','png','gif','pdf','txt'];
if (!is_dir($uploadDir)) @mkdir($uploadDir, 0755, true);
$msg = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!isset($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
$msg = '上傳失敗: ' . ($_FILES['file']['error'] ?? '未知錯誤');
} else {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES['file']['tmp_name']);
$ext = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION));
if (!in_array($ext, $allowedExt, true)) {
$msg = '不允許的文件類型';
} elseif ($_FILES['file']['size'] > $maxSize) {
$msg = '文件過大(限制 2MB)';
} else {
$newName = bin2hex(random_bytes(8)) . '.' . $ext;
$dest = $uploadDir . DIRECTORY_SEPARATOR . $newName;
if (move_uploaded_file($_FILES['file']['tmp_name'], $dest)) {
$msg = "上傳成功!文件: $newName";
} else {
$msg = '文件移動失敗,請檢查目錄權限';
}
}
}
}
?>
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>簡單上傳</title></head><body>
<h1>文件上傳(單文件)</h1>
<p style="color:green"><?= $msg ?></p>
<form method="post" enctype="multipart/form-data">
<input type="hidden" name="MAX_FILE_SIZE" value="<?= $maxSize ?>">
<input type="file" name="file" required>
<button type="submit">上傳</button>
</form>
</body></html>
<?php
// upload_multi.php
$uploadDir = __DIR__ . '/uploads';
$maxSize = 5 * 1024 * 1024;
$allowedMimes = ['image/jpeg','image/png','image/gif','image/webp','application/pdf'];
if (!is_dir($uploadDir)) @mkdir($uploadDir, 0755, true);
$results = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['files'])) {
$files = $_FILES['files'];
$count = count($files['name']);
for ($i = 0; $i < $count; $i++) {
$err = $files['error'][$i];
if ($err !== UPLOAD_ERR_OK) {
$results[] = ['name' => $files['name'][$i], 'ok' => false, 'msg' => "錯誤代碼: $err"];
continue;
}
$tmp = $files['tmp_name'][$i];
$size = $files['size'][$i];
$name = $files['name'][$i];
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $tmp);
$ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
if (!in_array($mime, $allowedMimes, true)) {
$results[] = ['name' => $name, 'ok' => false, 'msg' => "類型不允許: $mime"];
continue;
}
if ($size > $maxSize) {
$results[] = ['name' => $name, 'ok' => false, 'msg' => '文件過大'];
continue;
}
$newName = bin2hex(random_bytes(10)) . '.' . $ext;
$dest = $uploadDir . DIRECTORY_SEPARATOR . $newName;
if (move_uploaded_file($tmp, $dest)) {
$results[] = ['name' => $name, 'ok' => true, 'saved' => $newName, 'url' => "/uploads/$newName"];
} else {
$results[] = ['name' => $name, 'ok' => false, 'msg' => '保存失敗'];
}
}
}
?>
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>多文件上傳</title></head><body>
<h1>多文件上傳</h1>
<form method="post" enctype="multipart/form-data">
<input type="file" name="files[]" multiple required>
<button type="submit">上傳選中文件</button>
</form>
<?php if ($results): ?>
<h2>結果</h2>
<ul>
<?php foreach ($results as $r): ?>
<li style="color:<?= $r['ok']?'green':'red' ?>">
<?= htmlspecialchars($r['name']) ?>: <?= $r['msg'] ?? '成功' ?>
<?php if ($r['ok']): ?> - <a href="<?= $r['url'] ?>" target="_blank">查看</a> <?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</body></html>
$_FILES['type']。bin2hex(random_bytes())),防覆蓋、防猜測、防注入。location /uploads { php_flag engine off; }、Apache SetHandler default-handler。upload_max_filesize、post_max_size、Nginx client_max_body_size、HTML MAX_FILE_SIZE 四層。UPLOAD_ERR_* 常量。$_FILES['tmp_name'],但異常終止時可能殘留,建議定時清理 sys_get_temp_dir()。<script>
async function uploadFiles(files) {
const fd = new FormData();
[...files].forEach(f => fd.append('files[]', f));
const res = await fetch('upload_multi.php', {method: 'POST', body: fd});
const html = await res.text();
// 簡單演示:直接替換 body(實際應解析 JSON 更新 DOM)
document.body.innerHTML = html;
}
document.querySelector('input[type=file]').addEventListener('change', e => {
if (e.target.files.length) uploadFiles(e.target.files);
});
</script>
本文提供了兩個「開箱即用」的 PHP 文件上傳示例:單文件同步表單、多文件 HTML5 表單。代碼包含 MIME 白名單驗證、隨機命名、大小限制、錯誤碼處理、目錄權限 等安全基線。實際項目中請根據業務體量擴展:分片斷點續傳、進度條、圖片壓縮/水印、病毒掃描、異步隊列、對象存儲直傳。