การตรวจสอบขนาดไฟล์ฝั่ง Client (Client-side Validation) ช่วยประหยัด Bandwidth และให้ UX ดีกว่า แต่ ต้องตรวจสอบฝั่ง Server อีกครั้งเสมอ (Client-side แก้ไขได้)
ตัวอย่าง: ตรวจสอบขนาดไฟล์ก่อนอัปโหลด
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Validate File Size</title>
<style>
body { font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; padding: 20px; }
.result { font-size: 18px; font-weight: 500; color: blueviolet; margin: 10px 0; padding: 15px; border-radius: 4px; }
.success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
.error { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
.warning { background: #fff3cd; color: #856404; border: 1px solid #ffeeba; }
input[type="file"] { margin: 10px 0; }
</style>
</head>
<body>
<h1>ตรวจสอบขนาดไฟล์ก่อนอัปโหลด</h1>
<input type="file" id="fileInput" onchange="validateFile()">
<div class="result" id="result"></div>
<h3>เลือกไฟล์เพื่อตรวจสอบขนาด (จำกัด 4MB)</h3>
<script>
const fileInput = document.getElementById("fileInput");
const result = document.getElementById("result");
const MAX_SIZE_MB = 4;
const MAX_SIZE_BYTES = MAX_SIZE_MB * 1024 * 1024;
function validateFile() {
result.innerHTML = "";
result.className = "result";
if (fileInput.files.length === 0) {
result.textContent = "ไม่ได้เลือกไฟล์";
result.classList.add("warning");
return;
}
const file = fileInput.files[0];
const fileSize = file.size; // Bytes
const fileSizeMB = (fileSize / (1024 * 1024)).toFixed(2);
result.innerHTML = `
ชื่อไฟล์: ${escapeHtml(file.name)}
ขนาด: ${fileSize} bytes (${fileSizeMB} MB)
ประเภท: ${file.type || "Unknown"}
แก้ไขล่าสุด: ${new Date(file.lastModified).toLocaleString("th-TH")}
`;
if (fileSize > MAX_SIZE_BYTES) {
result.innerHTML += `
❌ ไฟล์ใหญ่เกินไป! สูงสุด ${MAX_SIZE_MB} MB`;
result.classList.add("error");
} else {
result.innerHTML += `
✅ ผ่านการตรวจสอบ - พร้อมอัปโหลด`;
result.classList.add("success");
}
}
function escapeHtml(text) {
const div = document.createElement("div");
div.textContent = text;
return div.innerHTML;
}
</script>
</body>
</html>
ผลลัพธ์
เลือกไฟล์ ≤ 4MB → ✅ สีเขียว "พร้อมอัปโหลด"
เลือกไฟล์ > 4MB → ❌ สีแดง "ไฟล์ใหญ่เกินไป!"
ขยาย: ตรวจสอบหลายไฟล์พร้อมกัน
<input type="file" id="multiFile" multiple>
<script>
document.getElementById("multiFile").addEventListener("change", (e) => {
const files = Array.from(e.target.files);
const MAX_SIZE = 5 * 1024 * 1024; // 5MB
const errors = [];
files.forEach(file => {
if (file.size > MAX_SIZE) {
errors.push(`${file.name} (${(file.size/1024/1024).toFixed(2)} MB) เกิน ${MAX_SIZE/1024/1024} MB`);
}
});
if (errors.length > 0) {
alert("ไฟล์ต่อไปนี้เกินขนาด:\n" + errors.join("\n"));
e.target.value = ""; // Clear selection
}
});
</script>
ขยาย: ตรวจสอบประเภทไฟล์ (File Type Validation)
const ALLOWED_TYPES = [
"image/jpeg", "image/png", "image/gif", "image/webp",
"application/pdf",
"text/plain"
];
function validateFileType(file) {
// ตรวจสอบ MIME Type
if (!ALLOWED_TYPES.includes(file.type)) {
return { valid: false, reason: `ประเภทไฟล์ไม่รองรับ: ${file.type}` };
}
// ตรวจสอบ Extension (Fallback)
const ext = file.name.split(".").pop().toLowerCase();
const allowedExts = ["jpg", "jpeg", "png", "gif", "webp", "pdf", "txt"];
if (!allowedExts.includes(ext)) {
return { valid: false, reason: `นามสกุลไฟล์ไม่รองรับ: .${ext}` };
}
return { valid: true };
}
⚠️ ข้อจำกัดของ Client-side Validation
- ผู้ใช้สามารถแก้ไข JavaScript / Bypass ได้ (DevTools)
- MIME Type สามารถปลอมได้ (
file.typeมาจาก Extension ไม่ใช่เนื้อหาจริง) - ต้อง Validate ที่ Server เสมอ (Node.js, PHP, Python, Java, etc.)
Server-side Validation (Node.js + Multer Example)
const multer = require("multer");
const upload = multer({
limits: { fileSize: 4 * 1024 * 1024 }, // 4MB
fileFilter: (req, file, cb) => {
const allowed = ["image/jpeg", "image/png", "application/pdf"];
if (allowed.includes(file.mimetype)) {
cb(null, true);
} else {
cb(new Error("Invalid file type"), false);
}
}
});
app.post("/upload", upload.single("file"), (req, res) => {
// ไฟล์ผ่านการตรวจสอบแล้ว
res.json({ success: true, filename: req.file.filename });
});