使用者點選檔案後,立即在頁面預覽圖片,並送至伺服器指定目錄儲存。核心分為客戶端預覽與伺服端接收兩部分。
<input type="file" id="imgInput" accept="image/*" />
<img id="preview" style="max-width:300px; display:none;" />
<script>
document.getElementById('imgInput').addEventListener('change', function(e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function(evt) {
const img = document.getElementById('preview');
img.src = evt.target.result;
img.style.display = 'block';
};
reader.readAsDataURL(file); // Base64 Data URL
});
</script>
支援 IE10+、所有現代瀏覽器。若需相容舊瀏覽器,可使用 Flash 上傳元件(如 SWFUpload)或 iframe 無刷新提交。
<?php
// upload.php
$targetDir = __DIR__ . '/uploads/';
if (!is_dir($targetDir)) mkdir($targetDir, 0755, true);
$file = $_FILES['image'] ?? null;
if (!$file || $file['error'] !== UPLOAD_ERR_OK) {
http_response_code(400);
exit(json_encode(['error' => '上傳失敗或無檔案']));
}
// 安全檢查:副檔名、MIME、檔案大小
$allowedExt = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if (!in_array($ext, $allowedExt)) {
exit(json_encode(['error' => '不允許的檔案類型']));
}
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $file['tmp_name']);
if (!in_array($mime, ['image/jpeg', 'image/png', 'image/gif', 'image/webp'])) {
exit(json_encode(['error' => '檔案內容非圖片']));
}
if ($file['size'] > 5 * 1024 * 1024) { // 5MB
exit(json_encode(['error' => '檔案過大']));
}
// 產生唯一檔名避免衝突
$newName = uniqid('img_', true) . '.' . $ext;
$dest = $targetDir . $newName;
if (move_uploaded_file($file['tmp_name'], $dest)) {
// 回傳可公開存取的 URL
echo json_encode(['url' => '/uploads/' . $newName]);
} else {
http_response_code(500);
echo json_encode(['error' => '伺服器儲存失敗']);
}
?>
$('#imgInput').on('change', function() {
const formData = new FormData();
formData.append('image', this.files[0]);
$.ajax({
url: 'upload.php',
type: 'POST',
data: formData,
processData: false,
contentType: false,
dataType: 'json',
success: function(res) {
if (res.url) {
$('#preview').attr('src', res.url).show();
alert('上傳成功:' + res.url);
} else {
alert('錯誤:' + res.error);
}
},
error: function() { alert('網路或伺服器錯誤'); }
});
});
input[multiple] + 迴圈 FormData.append()。drop 事件,取得 e.originalEvent.dataTransfer.files。xhr: function() { ... } 監聽 progress 事件。