// N4 — ถอดรหัสชื่อไฟล์ที่ FormData ของ Server Action ส่งมา // browser ใส่ชื่อไฟล์ (UTF-8) ลง header Content-Disposition ของ multipart body ตรง ๆ // แต่ undici ของ Node (ตัว parse request.formData() ที่ Next.js ใช้) ถอดรหัส header // เป็น latin1 ทำให้ชื่อที่ไม่ใช่ ASCII เพี้ยน ("คำร้อง.pdf" → "คำร้อง.pdf") // — เข้ารหัสกลับเป็น byte แล้วถอดด้วย UTF-8 จะได้ชื่อเดิมคืน // guard 2 ชั้นกันแตะชื่อที่ถูกต้องอยู่แล้ว: ชื่อที่ undici ถอดมามีแต่ตัวอักษร // ช่วง U+0000–U+00FF เท่านั้น ดังนั้นไม่มีตัวไหนใน U+0080–U+00FF เลย = ASCII ล้วนหรือ // ชื่อที่ส่งมาถูกต้อง (ไทยอยู่ U+0E00+) = ไม่แต้อยู่เดิม / ถอดแล้วได้ U+FFFD // (ไบต์ไม่ประกอบเป็น UTF-8 ที่สมบูรณ์ — ชื่อเป็น latin1 จริง) = เก็บของเดิมไว้ const LATIN1_MOJIBAKE_RE = /[\u0080-ÿ]/; export function decodeUploadFilename(name: string): string { if (!LATIN1_MOJIBAKE_RE.test(name)) return name; const fixed = Buffer.from(name, "latin1").toString("utf8"); return fixed.includes("�") ? name : fixed; }