ทำให้การอัปโหลดไฟล์ที่มีผู้ใช้จำนวนมากปลอดภัยด้วย signed URLs, การตรวจชนิดและขนาดที่เข้มงวด, pipeline สแกนมัลแวร์, และกฎสิทธิ์ที่ยังคงรวดเร็วเมื่อทราฟฟิกเพิ่มขึ้น

invoice.pdf อาจเป็นอย่างอื่น อย่าเชื่อสกุลหรือการตรวจใน UI ตรวจยืนยันจากไบต์จริงหลังอัปโหลด\n\nมัลแวร์ต่างออกไป โดยทั่วไปคุณไม่สามารถสแกนทุกอย่างก่อนอัปโหลดเสร็จได้โดยไม่ทำให้ประสบการณ์แย่ รูปแบบปกติคือสแกนแบบอะซิงโครนัส กักกันรายการที่น่าสงสัย และบล็อกการเข้าถึงจนกว่าจะผ่านการสแกน\n\nการเข้าถึงโดยไม่ได้รับอนุญาตมักทำความเสียหายมากที่สุด ถือว่าทุกการอัปโหลดและการดาวน์โหลดเป็นการตัดสินสิทธิ์ ผู้ใช้ควรอัปโหลดเฉพาะไปยังที่ที่พวกเขาเป็นเจ้าของ (หรือได้รับสิทธิ์เขียน) และดาวน์โหลดเฉพาะไฟล์ที่พวกเขาเห็นได้\n\nสำหรับหลายแอป นโยบาย v1 ที่มั่นคงคือ:\n\n- บังคับขนาดสูงสุดและหมวดหมู่ที่อนุญาต (ภาพ, PDF ฯลฯ)\n- ยืนยันชนิดไฟล์จริงฝั่งเซิร์ฟเวอร์หลังอัปโหลด\n- สแกนแบบอะซิงโครนัสและกักกันจนกว่าจะสะอาด\n- ต้องมีการอนุญาตชัดเจนสำหรับการอัปโหลดและการดาวน์โหลด\n- บันทึกและแจ้งเตือนเมื่อเกิดความล้มเหลวซ้ำ (ขนาด ชนิด สิทธิ์)\n\n## สถาปัตยกรรมอัปโหลดที่ปฏิบัติได้และยังเร็ว\n\nวิธีที่เร็วที่สุดคือเก็บเซิร์ฟเวอร์แอปของคุณให้ออกห่างจากการ "รับบิต" แทนที่จะส่งไฟล์ทั้งหมดผ่านแบ็กเอนด์ ให้ไคลเอนต์อัปโหลดตรงไปยัง object storage โดยใช้ signed URL ที่มีอายุสั้น แบ็กเอนด์ของคุณโฟกัสที่การตัดสินและการบันทึก ไม่ใช่การย้ายกิกะไบต์\n\nการแยกแบบนี้ง่าย: แบ็กเอนด์ตอบว่า "ใครอัปโหลดอะไร และไปที่ไหน" ในขณะที่ storage รับข้อมูลไฟล์ การออกแบบนี้ตัดคอขวดที่พบบ่อย: เซิร์ฟเวอร์แอปทำงานซ้ำ (auth แล้ว proxy ไฟล์) จนหมด CPU หน่วยความจำ หรือเครือข่ายภายใต้โหลด\n\n### ส่วนประกอบขั้นต่ำที่ควรมี\n\nเก็บเรคคอร์ดการอัปโหลดเล็กๆ ในฐานข้อมูลของคุณ (เช่น PostgreSQL) เพื่อให้แต่ละไฟล์มีเจ้าของและวงจรชีวิตชัดเจน สร้างเรคคอร์ดนี้ก่อนเริ่มอัปโหลด แล้วอัปเดตตามเหตุการณ์ที่เกิดขึ้น\n\nฟิลด์ที่มักให้ผลดีรวมถึง owner และ tenant/workspace identifiers, storage object key, status, ขนาดที่ระบุและ MIME type, และ checksum ที่คุณสามารถยืนยันได้\n\n### วางแผนสถานะการอัปโหลดล่วงหน้า\n\nจัดการการอัปโหลดเหมือน state machine เพื่อให้การตรวจสิทธิ์ยังถูกต้องเมื่อเกิด retry\n\nชุดสถานะที่ปฏิบัติได้คือ:\n\n- requested\n- uploaded\n- scanned\n- approved\n- rejected\n\nอนุญาตให้ไคลเอนต์ใช้ signed URL ก็ต่อเมื่อแบ็กเอนด์สร้างเรคคอร์ด requested ก่อน หลังจาก storage ยืนยันการอัปโหลด ให้ย้ายสถานะเป็น uploaded และเริ่มการสแกนมัลแวร์ในพื้นหลัง แล้วเปิดให้เข้าถึงไฟล์เมื่อมันถูก approved เท่านั้น\n\n## ขั้นตอนทีละขั้น: การอัปโหลดด้วย signed URL โดยไม่เป็นคอขวด\n\nเริ่มเมื่อผู้ใช้กดอัปโหลด แอปเรียกแบ็กเอนด์เพื่อเริ่มการอัปโหลดพร้อมรายละเอียดพื้นฐาน เช่น ชื่อไฟล์ ขนาดไฟล์ และการใช้งานที่ตั้งใจ (avatar, invoice, attachment) แบ็กเอนด์ตรวจสิทธิ์สำหรับเป้าหมายเฉพาะ สร้างเรคคอร์ดการอัปโหลด และคืน signed URL ที่มีอายุสั้น\n\nSigned URL ควรถูกจำกัดอย่างแคบIdeally ให้อนุญาตการอัปโหลดเพียงครั้งเดียวไปยัง object key เดียวเท่านั้น มีอายุสั้น และมีเงื่อนไขชัดเจน (ขีดจำกัดขนาด ชนิดเนื้อหาอนุญาต และ checksum ถ้ามี)\n\nเบราว์เซอร์อัปโหลดตรงไปยัง storage โดยใช้ URL นั้น เมื่อเสร็จ ไคลเอนต์เรียกแบ็กเอนด์อีกครั้งเพื่อ finalize ขณะ finalize ให้ตรวจสิทธิ์อีกครั้ง (ผู้ใช้อาจถูกถอดสิทธิ์) และยืนยันสิ่งที่ลงใน storage จริง: ขนาด ชนิดเนื้อหาที่ตรวจพบ และ checksum หากใช้ ทำให้ finalize เป็น idempotent เพื่อให้ retry ไม่สร้างรายการซ้ำ\n\nจากนั้นทำเครื่องหมายเรคคอร์ดเป็น uploaded และทริกเกอร์การสแกนแบบ background (queue/job) UI สามารถแสดงสถานะว่า “Processing” ขณะสแกนทำงาน\n\n## การตรวจชนิดและขนาดที่เชื่อถือได้\n\n### ตรวจอะไร และที่ไหน\n\nการเชื่อสกุลไฟล์คือเหตุผลที่ invoice.pdf.exe จบในบัคเก็ตของคุณ ถือการตรวจเป็นชุดการเช็คที่ทำซ้ำได้หลายจุด\n\nเริ่มจากขีดจำกัดขนาด ใส่ขนาดสูงสุดลงในนโยบาย signed URL (หรือ pre-signed POST conditions) เพื่อให้ storage ปฏิเสธการอัปโหลดเกินขนาดตั้งแต่ต้น บังคับขีดจำกัดเดียวกันอีกครั้งเมื่อแบ็กเอนด์บันทึกเมตาดาต้า เพราะไคลเอนต์ยังพยายามหลีกเลี่ยง UI ได้\n\nการตรวจชนิดควรอิงจากเนื้อหา ไม่ใช่ชื่อไฟล์ ตรวจดูไบต์เริ่มต้นของไฟล์ (magic bytes) เพื่อยืนยันว่าตรงกับที่คาดไว้ ไฟล์ PDF จริงเริ่มด้วย %PDF และ PNG เริ่มด้วยลายเซ็นคงที่ ถ้าเนื้อหาไม่ตรงกับ allowlist ให้ปฏิเสธแม้ว่านามสกุลจะดูถูกต้องก็ตาม\n\nเก็บ allowlist ให้เฉพาะเจาะจงตามฟีเจอร์ ตัวอย่างเช่น อัปโหลด avatar อาจอนุญาตเฉพาะ JPEG และ PNG ส่วนฟีเจอร์เอกสารอาจอนุญาต PDF และ DOCX วิธีนี้ลดความเสี่ยงและทำให้กฎอธิบายง่ายขึ้น\n\n### Checksums และชื่อไฟล์\n\nอย่าไว้ใจชื่อไฟล์ต้นฉบับเป็น storage key ทำให้ชื่อนั้นสำหรับแสดง (ลบอักขระแปลก ตัดความยาว) แต่เก็บ object key ของคุณเอง เช่น UUID + นามสกุลที่คุณกำหนดหลังตรวจชนิด\n\nเก็บ checksum (เช่น SHA-256) ในฐานข้อมูลและเปรียบเทียบภายหลังระหว่างการประมวลผลหรือการสแกน ซึ่งช่วยจับความเสียหาย การอัปโหลดไม่สมบูรณ์ หรือการดัดแปลง โดยเฉพาะเมื่อมีการ retry ภายใต้โหลด\n\n## การสแกนมัลแวร์ที่ไม่ทำให้ผู้ใช้ต้องรอนาน\n\nการสแกนมัลแวร์สำคัญ แต่ไม่ควรเป็นเส้นทางวิกฤต ยอมรับการอัปโหลดอย่างรวดเร็ว แล้วถือว่าไฟล์ถูกบล็อกจนกว่าจะผ่านการสแกน\n\n### รูปแบบอะซิงโครนัส\n\nสร้างเรคคอร์ดการอัปโหลดด้วยสถานะเช่น pending_scan UI สามารถแสดงไฟล์ได้ แต่ไม่ควรใช้งานได้\n\nการสแกนมักถูกรันเมื่อมี event จาก storage เมื่อตัวออบเจ็กต์ถูกสร้าง โดยการเผยแพร่ job ไปยังคิวหลังการอัปโหลดเสร็จ หรือทั้งสองวิธี (คิว + event เป็น backstop)\n\nสแกนเนอร์จะดาวน์โหลดหรือสตรีมออบเจ็กต์ รันการสแกน แล้วเขียนผลกลับฐานข้อมูล เก็บข้อมูลสำคัญ: สถานะการสแกน เวอร์ชันสแกนเนอร์ เวลาทำงาน และผู้ที่ร้องขอการอัปโหลด เส้นทาง audit นี้ช่วยทีมซัพพอร์ตเมื่อมีคนถามว่า “ทำไมไฟล์ฉันถูกบล็อก?”\n\n### เกิดอะไรขึ้นเมื่อไฟล์สแกนไม่ผ่าน\n\nอย่าปล่อยให้ไฟล์ที่ล้มเหลวปะปนกับไฟล์สะอาด เลือกนโยบายหนึ่งและใช้สม่ำเสมอ: กักกันและปิดการเข้าถึง หรือ ลบถ้าไม่จำเป็นต้องเก็บเพื่อสืบสวน\n\nไม่ว่าเลือกแบบไหน ให้ข้อความแก่ผู้ใช้สุภาพและชัดเจน บอกว่ามีอะไรเกิดขึ้นและต้องทำอย่างไรต่อ (อัปโหลดใหม่ ติดต่อซัพพอร์ต) แจ้งทีมถ้ามีความล้มเหลวจำนวนมากในระยะสั้น\n\nสำคัญที่สุด ให้มีกฎชัดเจนสำหรับการดาวน์โหลดและพรีวิว: ให้บริการเฉพาะไฟล์ที่ถูกทำเครื่องหมายว่า approved เท่านั้น อย่างอื่นส่งคำตอบที่ปลอดภัยเช่น “ไฟล์กำลังถูกตรวจสอบ”\n\n## การตรวจสิทธิ์ที่ยังถูกต้องเมื่อระบบมีโหลดสูง\n\nการอัปโหลดที่เร็วดี แต่ถ้าคนผิดสามารถแนบไฟล์ไปยัง workspace ผิด คุณมีปัญหามากกว่าคำร้องขอช้า กฎง่ายที่สุดและเข้มแข็งที่สุดคือ: แต่ละเรคคอร์ดไฟล์เป็นของ tenant เดียว (workspace/org/project) และมี owner หรือ creator ชัดเจน\n\nตรวจสิทธิ์สองครั้ง: เมื่่อออก signed upload URL และอีกครั้งเมื่อมีคนพยายามดาวน์โหลดหรือดูไฟล์ การตรวจครั้งแรกหยุดการอัปโหลดที่ไม่ได้รับอนุญาต ครั้งที่สองปกป้องคุณหากการเข้าถึงถูกยกเลิก URL รั่ว หรือบทบาทผู้ใช้เปลี่ยนหลังอัปโหลด\n\nหลักการ least privilege ทำให้ทั้งความปลอดภัยและประสิทธิภาพคาดเดาได้ แทนที่จะมีสิทธิ์กว้างๆ “files” ให้แยกบทบาท เช่น “can upload”, “can view”, และ “can manage (delete/share)” คำขอหลายรายการจะกลายเป็นการ lookup ที่เร็ว (user, tenant, action) แทนการคำนวณกฎที่หนักหน่วง\n\nเพื่อป้องกันการเดา ID หลีกเลี่ยง ID ไฟล์แบบเรียงกันใน URL และ API ใช้ตัวระบุทึบและให้ storage keys เดายาก Signed URLs เป็นช่องทางขนส่ง ไม่ใช่ระบบสิทธิ์ของคุณ\n\nการแชร์ไฟล์มักทำให้ระบบช้าและยุ่ง ใช้การแชร์เป็นข้อมูลชัดเจน ไม่ใช่การเข้าถึงโดยปริยาย วิธีง่ายๆ คือเรคคอร์ดการแชร์แยกต่างหากที่ให้สิทธิ์แก่ผู้ใช้หรือกลุ่มต่อไฟล์หนึ่งไฟล์ พร้อม expiry ถ้าจำเป็น\n\n## รักษาความเร็วเมื่อปริมาณและขนาดไฟล์เพิ่มขึ้น\n\nเมื่อคนพูดถึงการสเกลการอัปโหลดที่ปลอดภัย มักเน้นการตรวจสอบความปลอดภัยแล้วลืมพื้นฐาน: การย้ายบิตคือช้าสุด เป้าหมายคือให้การรับส่งไฟล์ใหญ่หลีกเลี่ยงเซิร์ฟเวอร์แอป เก็บ retries ใต้การควบคุม และอย่าให้การตรวจความปลอดภัยกลายเป็นคิวที่ไม่มีขอบเขต\n\n### ทำให้ไฟล์ใหญ่คาดเดาได้\n\nสำหรับไฟล์ใหญ่ ใช้ multipart หรือ chunked uploads เพื่อให้การเชื่อมต่อไม่เสถียรไม่ต้องเริ่มใหม่ทั้งหมด ชิ้นส่วนยังช่วยให้บังคับขีดจำกัดชัดเจน: ขนาดรวมสูงสุด ขนาดชิ้นสูงสุด และเวลาการอัปโหลดสูงสุด\n\nตั้ง timeout และ retries ของไคลเอนต์อย่างมีเหตุผล ไม่กี่ครั้งช่วยผู้ใช้จริงได้ แต่ retry ไม่จำกัดอาจเผาต้นทุน โดยเฉพาะบนเครือข่ายมือถือ ตั้ง timeout ต่อชิ้นสั้น ระบุ retry cap เล็กน้อย และกำหนด deadline แข็งสำหรับการอัปโหลดทั้งหมด\n\n### ควบคุมขั้นตอน “create upload”\n\nSigned URLs ช่วยให้เส้นทางข้อมูลหนักเร็ว แต่คำขอที่สร้าง signed URL ยังคงเป็นจุดร้อน ปกป้องมันเพื่อให้ยังตอบสนอง:\n\n- rate-limit “create upload” ต่อผู้ใช้และต่อ IP\n- บังคับขีดจำกัดขนาดก่อนออก signed URL\n- ให้ TTL สั้นเพื่อให้ URL ที่ไม่ได้ใช้หมดอายุเร็ว\n- ติดตามการอัปโหลดที่กำลังทำเพื่อไม่ให้ผู้ใช้เริ่มร้อยเป็นร้อยครั้ง\n- ใช้ idempotency keys เพื่อให้รีเฟรชไม่สร้างการอัปโหลดซ้ำ\n\nlatency ยังขึ้นกับภูมิศาสตร์ เก็บแอป, storage, และ worker สแกนใน region เดียวกันเมื่อเป็นไปได้ ถ้าต้องโฮสต์ตามประเทศเพื่อตรงตามข้อกำหนด วางแผนการ routing ตั้งแต่แรกเพื่อไม่ให้การอัปโหลดเด้งข้ามทวีป แพลตฟอร์มที่รันบน AWS ทั่วโลก (เช่น Koder.ai) สามารถวางงานให้ใกล้ผู้ใช้เมื่อมีข้อกำหนดเรื่องข้อมูลประจำประเทศ\n\nสุดท้าย วางแผนการดาวน์โหลด ไม่ใช่แค่การอัปโหลด ให้บริการไฟล์ด้วย signed download URLs และตั้งกฎ caching ตามชนิดไฟล์และระดับความเป็นส่วนตัว ทรัพยากรสาธารณะเก็บแคชได้นานกว่า ใบเสร็จส่วนตัวควรมีอายุสั้นและผ่านการตรวจสิทธิ์เสมอ\n\n## ตัวอย่างสถานการณ์: ใบแจ้งหนี้และใบเสร็จในแอปหลายผู้ใช้\n\nจินตนาการแอปธุรกิจขนาดเล็กที่พนักงานอัปโหลดใบแจ้งหนี้และรูปใบเสร็จ แล้วผู้จัดการอนุมัติให้เบิกจ่าย นี่คือจุดที่การออกแบบการอัปโหลดมีผลจริง: มีผู้ใช้จำนวนมาก รูปใหญ่ และเรื่องเงินเกี่ยวข้อง\n\nโฟลว์ที่ดีใช้สถานะชัดเจนเพื่อให้ทุกคนรู้ว่าเกิดอะไรขึ้นและคุณสามารถอัตโนมัติส่วนที่น่าเบื่อ: ไฟล์ลงที่ object storage และคุณเก็บเรคคอร์ดผูกกับ user/workspace/expense; งานพื้นหลังสแกนไฟล์และสกัด metadata พื้นฐาน (เช่น MIME type ที่ตรวจพบ); จากนั้นรายการถูกอนุมัติและใช้งานได้ในรายงาน หรือถูกปฏิเสธและบล็อก\n\nผู้ใช้ต้องการฟีดแบ็กที่เร็วและเฉพาะเจาะจง ถ้าไฟล์ใหญ่เกิน ให้แสดงขีดจำกัดและขนาดปัจจุบัน (เช่น: “ไฟล์ขนาด 18 MB ขีดจำกัด 10 MB”) ถ้าชนิดไฟล์ไม่ตรง บอกว่าอนุญาตอะไรบ้าง (“อัปโหลด PDF, JPG, หรือ PNG”) ถ้าสแกนล้มเหลว ให้ข้อมูลสุภาพและปฏิบัติได้ (“ไฟล์นี้อาจไม่ปลอดภัย กรุณาอัปโหลดสำเนาใหม่”)\n\nทีมซัพพอร์ตต้องการเส้นทางที่ช่วยดีบักโดยไม่ต้องเปิดไฟล์: upload ID, user ID, workspace ID, timestamps สำหรับ created/uploaded/scan started/scan finished, result codes (too large, type mismatch, scan failed, permission denied), รวมถึง storage key และ checksum\n\nการอัปโหลดซ้ำและการแทนที่เป็นเรื่องปกติ จัดให้เป็นการอัปโหลดใหม่ ผูกกับ expense เดิมเป็นเวอร์ชันใหม่ เก็บประวัติ (ใครแทนที่เมื่อไหร่) และทำเครื่องหมายเฉพาะเวอร์ชันล่าสุดว่าเป็นเวอร์ชัน active ถ้าคุณสร้างแอปนี้บน Koder.ai แผนนี้แมปได้ชัดเจนกับตาราง uploads และตาราง expense_attachments ที่มีฟิลด์ version\n\n## ข้อผิดพลาดที่พบบ่อยและการแก้ไขง่ายๆ\n\nบั๊กการอัปโหลดส่วนใหญ่ไม่ใช่แฮ็กหรู แต่เป็นทางลัดเล็กๆ ที่กลายเป็นความเสี่ยงเมื่อปริมาณโตขึ้น\n\n### ห้าข้อผิดพลาดที่พบบ่อยที่สุด\n\n- เชื่อการตรวจฝั่งไคลเอนต์อย่างเดียว แก้: ตรวจอีกครั้งฝั่งเซิร์ฟเวอร์โดยใช้ไบต์จริง (magic bytes) และบังคับขีดจำกัดขนาดด้วย metadata ของ storage ไม่ใช่แค่ข้อมูลจากเบราว์เซอร์\n- ให้ signed URLs มีอายุยาว แก้: ทำให้สั้น (เป็นนาที) จำกัดให้ใช้ครั้งเดียว และบันทึกการออกทุกครั้ง\n- ให้ไฟล์ดาวน์โหลดได้ก่อนการสแกนเสร็จ แก้: อัปโหลดไปยังที่กักกัน สแกนแบบอะซิงโครนัส แล้วค่อย promote หรือให้บริการหลังผลสะอาด\n- ใช้ชื่อหรือตำแหน่งที่ผู้ใช้ให้มาเป็น storage key แก้: สร้าง object key เอง (UUID) และเก็บชื่อเดิมเป็น metadata สำหรับแสดง\n- ข้ามการตรวจสิทธิ์ตอนดาวน์โหลด แก้: ถือว่าการดาวน์โหลดเป็นการตัดสินแยกต่างหาก ตรวจ ownership, การเป็นสมาชิก workspace, และกฎการแชร์ทุกครั้งที่ออก signed download URL\n\n### การแก้ไขง่ายๆ ที่ป้องกันคอขวด\n\nการเพิ่มการตรวจไม่จำเป็นต้องทำให้การอัปโหลดช้า แยกเส้นทางเร็วออกจากเส้นทางหนัก\n\nทำการตรวจอย่างรวดเร็วแบบ synchronous (auth, ขนาด, ชนิดที่อนุญาต, rate limits) แล้วส่งการสแกนและการตรวจละเอียดไปให้ worker ใน background ผู้ใช้ยังทำงานต่อได้ขณะที่ไฟล์ขยับจาก “uploaded” เป็น “ready” ถ้าคุณสร้างด้วยตัวช่วยแบบ chat-based อย่าง Koder.ai ให้รักษามุมมองเดียวกัน: ทำให้ endpoint การอัปโหลดเล็กและเข้มงวด แล้วดันการสแกนและหลังประมวลผลไปเป็น jobs\n\n## เช็คลิสต์ด่วนและขั้นตอนต่อไป\n\nก่อนส่งมอบการอัปโหลด ให้กำหนดว่า “พอกับ v1” หมายถึงอะไร ทีมมักเจอปัญหาโดยจับกฎเข้มงวด (บล็อกผู้ใช้จริง) ผสมกับกฎขาดหาย (ชวนให้เกิดการใช้งานในทางไม่ดี) เริ่มจากเล็ก แต่ทำให้แน่ใจว่าแต่ละการอัปโหลดมีเส้นทางชัดจาก “received” ถึง “allowed to download”\n\nเช็คลิสต์ก่อนปล่อย:\n\n- บังคับขีดจำกัดขนาดก่อน (ก่อนที่ค่าเก็บข้อมูลจะเพิ่ม)\n- ใช้ allowlist ชนิดไฟล์ ตรวจจากเนื้อหา (magic bytes) ไม่ใช่แค่ชื่อไฟล์\n- กักกันจนกว่าจะผ่านการสแกน: อย่าให้ผู้อื่นเข้าดูไฟล์ก่อน\n- ตรวจสิทธิ์การดาวน์โหลดทุกครั้ง\n- เก็บ audit logs สำหรับการอัปโหลด ผลการสแกน และความพยายามดาวน์โหลด\n\nถ้าต้องการนโยบายขั้นต่ำ ให้เรียบง่าย: ขีดจำกัดขนาด, allowlist ชนิดไฟล์แคบ, การอัปโหลดด้วย signed URL, และ “กักกันจนกว่าจะผ่านการสแกน” เพิ่มฟีเจอร์ที่สวยงามทีหลัง (พรีวิว ชนิดเพิ่ม การประมวลผลซ้ำในพื้นหลัง) เมื่เส้นทางหลักมั่นคงแล้ว\n\nการมอนิเตอร์คือสิ่งที่ทำให้ “เร็ว” ไม่กลายเป็น “ช้าลึกลับ” ขณะที่คุณเติบโต ติดตามอัตราความล้มเหลวการอัปโหลด (ฝั่งไคลเอนต์ vs เซิร์ฟเวอร์/storage), อัตราความล้มเหลวของการสแกนและความล่าช้าในการสแกน, เวลาอัปโหลดเฉลี่ยตามกลุ่มขนาดไฟล์, การปฏิเสธการอนุญาตในการดาวน์โหลด, และรูปแบบ egress ของ storage\n\nรันการทดสอบโหลดขนาดเล็กด้วยขนาดไฟล์ที่สมจริงและเครือข่ายโลกจริง (ข้อมูลมือถือทำงานต่างจาก Wi‑Fi ในออฟฟิศ) แก้ timeout และ retry ก่อนปล่อยจริง\n\nถ้าคุณกำลังนำไปใช้งานใน Koder.ai (koder.ai), Planning Mode เป็นที่ที่ใช้งานได้จริงเพื่อแม็ปสถานะการอัปโหลดและ endpoints ก่อน แล้วค่อยสร้างแบ็กเอนด์และ UI รอบโฟลว์นั้น Snapshots และ rollback ก็ช่วยเมื่อคุณปรับขีดจำกัดหรือกฎการสแกน\nใช้การอัปโหลดตรงไปยัง object storage ด้วย signed URLs ที่มีอายุสั้น เพื่อไม่ให้เซิร์ฟเวอร์ของแอปต้องสตรีมบิตไฟล์ เซิร์ฟเวอร์ของคุณควรโฟกัสที่การตัดสินสิทธิ์และบันทึกสถานะการอัปโหลด แทนที่จะย้ายกิกะไบต์เอง
เช็คสองครั้ง: ครั้งแรกเมื่อคุณสร้างการอัปโหลดและออก signed URL และอีกครั้งเมื่อ finalize และเมื่อให้ดาวน์โหลด Signed URLs เป็นแค่ช่องทางการส่งเท่านั้น แอปของคุณยังต้องมีการตรวจสิทธิ์ที่ผูกกับเรคคอร์ดไฟล์และ tenant/workspace
จัดการเป็น state machine เพื่อให้การ retry และความล้มเหลวบางส่วนไม่เปิดช่องทางความเสี่ยง โฟลว์ยอดนิยมคือ requested, uploaded, scanned, approved, rejected และอนุญาตการดาวน์โหลดได้เฉพาะเมื่อสถานะเป็น approved
ใส่ขีดจำกัดเป็นจำนวนไบต์ลงใน signed URL policy (หรือ pre-signed POST conditions) เพื่อให้ storage ปฏิเสธไฟล์ใหญ่ตั้งแต่ต้น แล้วบังคับขีดจำกัดเดียวกันอีกครั้งตอน finalize โดยใช้เมตาดาต้าจาก storage เพื่อป้องกันการข้ามฝั่งลูกค้า
ไม่ควรเชื่อสกุลไฟล์หรือ MIME type จากเบราว์เซอร์ ตรวจสอบจากไบต์จริงของไฟล์หลังอัปโหลด (เช่น magic bytes) แล้วเทียบกับ allowlist ของฟีเจอร์นั้นๆ
อย่าบล็อกผู้ใช้ระหว่างการสแกน ยอมรับการอัปโหลดอย่างรวดเร็ว กักกันไฟล์ แล้วสแกนแบบ background ให้อนุญาตดาวน์โหลด/พรีวิวเมื่อผลสแกนเป็นสะอาด
เลือกนโยบายให้ชัดเจน: กักกันและตัดการเข้าถึง หรือ ลบไฟล์ถ้าไม่ต้องเก็บเพื่อสืบสวน แจ้งผู้ใช้ด้วยข้อความสุภาพและชัดเจน พร้อมเก็บ audit เพื่อให้ทีมซัพพอร์ตอธิบายได้โดยไม่ต้องเปิดไฟล์
อย่าใช้ชื่อไฟล์จากผู้ใช้เป็น storage key สร้าง object key ที่เดายาก (เช่น UUID) เก็บชื่อเดิมไว้เป็น metadata สำหรับแสดงหลังจาก normalize
ใช้ multipart หรือ chunked uploads เพื่อให้การเชื่อมต่อที่ไม่เสถียรไม่ต้องเริ่มใหม่ทั้งหมด กำหนด retries ให้พอเหมาะ ตั้ง timeout ต่อชิ้นและมี deadline สำหรับการอัปโหลดทั้งหมด
เก็บเรคคอร์ดการอัปโหลดเล็กๆ ที่มี owner, tenant/workspace, object key, status, timestamps, detected type, ขนาด และ checksum (ถ้าใช้) ซึ่งจะช่วยให้ debug ปัญหาได้โดยไม่ต้องเปิดไฟล์