เก็บรูปที่ผู้ใช้อัปโหลดไม่ให้หาย ด้วยพื้นที่เก็บไฟล์ถาวร (/bw-data)

ทำไมรูปที่ผู้ใช้อัปโหลดหายหลังนำขึ้นเวอร์ชันใหม่ และวิธีเปิดพื้นที่เก็บไฟล์ถาวร /bw-data บน BrewInTH 3 ทาง พร้อมกติกาเรื่องขนาดและวิธีทดสอบ
คุณให้ AI ทำเว็บที่ให้สมาชิกอัปโหลดรูปโปรไฟล์ หรือให้ลูกค้าแนบสลิปโอนเงิน ทดสอบแล้วทุกอย่างปกติ แต่พอแก้โค้ดแล้วนำขึ้นเวอร์ชันใหม่ รูปที่เคยอัปโหลดหายหมด เหลือแต่กรอบรูปแตก หรือหนักกว่านั้น แอปอัปโหลดไม่ได้ตั้งแต่ครั้งแรกเพราะขึ้นข้อความ Read-only file system
ไม่ใช่บั๊กของ AI และไม่ใช่เว็บพัง แต่เป็นวิธีที่แอปบน BrewInTH ทำงาน บทความนี้อธิบายว่าทำไมไฟล์หาย และวิธีเปิด พื้นที่เก็บไฟล์ถาวร (/bw-data) ให้รูป เอกสาร และไฟล์ที่ผู้ใช้ส่งเข้ามาอยู่ครบทุกครั้งที่นำขึ้นเวอร์ชันใหม่
สรุปสั้นก่อนอ่าน
📁 ทุกครั้งที่นำขึ้นเวอร์ชันใหม่ แอปเริ่มจากโค้ดชุดใหม่ ไฟล์ที่แอปเขียนไว้ในโฟลเดอร์โค้ดจึงไม่ตามมา
📁 ข้อมูลในฐานข้อมูลไม่หาย ส่วน "ไฟล์" (รูป PDF ไฟล์ SQLite) ต้องเก็บในพื้นที่เก็บไฟล์ถาวร
📁 เปิดได้ 3 ทาง: ตั้งเองในแท็บ ตั้งค่าแอป, ให้ AI ตั้งให้ หรือให้หน้า อัปโหลดแล้วขึ้นเว็บ เปิดให้อัตโนมัติ
📁 ขนาดรวมของทุกโปรเจกต์ไม่เกินพื้นที่ของแพ็กเกจ เพิ่มขนาดได้ แต่ลดลงไม่ได้
📁 แอดออน Backups สำรองพื้นที่ /bw-data ให้ด้วย
ทำไมไฟล์ที่ผู้ใช้อัปโหลดถึงหาย
ลองนึกภาพว่าแอปของคุณเหมือนร้านที่ตกแต่งใหม่ทั้งร้านทุกครั้งที่มีเวอร์ชันใหม่ BrewInTH สร้างแอปขึ้นใหม่จากโค้ดชุดล่าสุดทุกครั้ง ข้อดีคือทุกเวอร์ชันสะอาด ตรงกับโค้ดที่ส่งมา ไม่มีของค้างจากรอบก่อน
แต่นั่นหมายความว่า ไฟล์ที่แอปเขียนลงในโฟลเดอร์โค้ดจะไม่อยู่ข้ามเวอร์ชัน และบน BrewInTH โฟลเดอร์ของแอปเป็นแบบอ่านอย่างเดียวด้วย แอปที่พยายามเขียนไฟล์ลงไปจะได้ข้อผิดพลาด Read-only file system ทันที แทนที่จะเขียนได้แล้วหายไปเงียบ ๆ ในภายหลัง
ของที่ไม่หายมีสองอย่าง
- ข้อมูลในฐานข้อมูล (PostgreSQL, MySQL, MariaDB, MongoDB) อยู่แยกจากแอปอยู่แล้ว นำขึ้นใหม่กี่ครั้งข้อมูลก็อยู่ครบ
- ไฟล์ในพื้นที่เก็บไฟล์ถาวร ดิสก์ของโปรเจกต์ที่ติดอยู่กับแอปทุกเวอร์ชัน เห็นได้ที่โฟลเดอร์
/bw-data

เว็บแบบ static (HTML CSS JavaScript ที่ไม่มีโปรแกรมฝั่ง server) ไม่ต้องใช้พื้นที่นี้ และจะไม่เห็นแผงนี้ในคอนโซล เพราะเว็บแบบนี้ไม่ได้เขียนไฟล์อะไรเอง
เก็บอะไรไว้ที่ไหนดี
กฎง่าย ๆ คือ
- ข้อมูลที่เป็นแถว ๆ เช่น สมาชิก ออเดอร์ คำตอบแบบสอบถาม เก็บในฐานข้อมูล
- ไฟล์ทั้งไฟล์ เช่น รูปโปรไฟล์ สลิปโอนเงิน ไฟล์ PDF ใบเสร็จ ไฟล์แนบ เก็บใน
/bw-dataแล้วเก็บแค่ชื่อไฟล์หรือ path ไว้ในฐานข้อมูล - แอปที่ใช้ SQLite (ฐานข้อมูลเป็นไฟล์เดียว เช่น
app.db) ไฟล์นั้นต้องอยู่ใน/bw-dataไม่อย่างนั้นข้อมูลจะหายทุกครั้งที่นำขึ้นใหม่
เปิดพื้นที่เก็บไฟล์ถาวร 3 ทาง

ทาง 1: ตั้งเองในคอนโซล
- เปิดโปรเจกต์ แล้วไปที่แท็บ ตั้งค่าแอป
- เลื่อนลงไปที่แผง พื้นที่เก็บไฟล์ถาวร (/bw-data)
- ในช่อง ขนาด เลือกขนาดที่ต้องการ รายการเลือกได้สูงสุด 80% ของพื้นที่ที่ยังว่างในแพ็กเกจ
- กด บันทึก ระบบมีผลกับเวอร์ชันถัดไปหรือเมื่อรีสตาร์ตแอป
จากนั้นบอก AI ให้แอปเขียนไฟล์ไว้ใต้ /bw-data เท่านั้น เช่น
แอปนี้มีฟีเจอร์อัปโหลดรูปโปรไฟล์และสลิปโอนเงิน
ให้เก็บไฟล์ที่ผู้ใช้อัปโหลดทั้งหมดไว้ใต้โฟลเดอร์ /bw-data/uploads เท่านั้น
(สร้างโฟลเดอร์ย่อยเองถ้ายังไม่มี) และเก็บแค่ชื่อไฟล์ไว้ในฐานข้อมูล
ทำ route สำหรับเปิดดูรูปจากโฟลเดอร์นั้น โดยตรวจว่าเป็นไฟล์ของผู้ใช้ที่มีสิทธิ์ดู
ตรวจชนิดไฟล์ (รับเฉพาะรูปและ PDF) และจำกัดขนาดไฟล์ไม่เกิน 5 MB
โฟลเดอร์ /data ที่เคยใช้ก่อนหน้านี้คือที่เดียวกัน แอปเดิมที่เขียนไว้ที่ /data ยังทำงานได้ตามปกติ แต่โค้ดใหม่ควรใช้ /bw-data
ทาง 2: ให้ AI agent ตั้งให้
ถ้าคุณใช้ coding agent (Claude Code, Codex, Cursor, Windsurf) นำเว็บขึ้นด้วยลิงก์และ token AI ตั้งพื้นที่นี้เองได้ด้วยคำสั่ง storage_set และทำได้มากกว่าการเปิดดิสก์อย่างเดียว คือบอกชื่อโฟลเดอร์ของแอปเอง เช่น uploads หรือ data แล้วโฟลเดอร์นั้นของแอปจะมาจากพื้นที่ถาวรทันที โดยไม่ต้องแก้โค้ด แอปที่เขียนไฟล์ลง uploads/ อยู่แล้วก็ใช้ต่อได้เลย
ก่อนนำขึ้น ระบบตรวจโค้ดใน ZIP ให้ด้วย ถ้าเห็นว่าโค้ดเขียนไฟล์ลงโฟลเดอร์ที่ยังไม่อยู่บนพื้นที่ถาวร จะเตือน AI พร้อมบอกคำสั่งที่ต้องเรียก AI ส่วนใหญ่จึงแก้ได้เองในรอบเดียว ถ้าอยากสั่งให้ชัด พิมพ์ต่อท้ายในแชตได้เลย
ก่อนนำขึ้น ตรวจว่าแอปเขียนไฟล์ลงโฟลเดอร์ไหนบ้าง (รูปที่ผู้ใช้อัปโหลด ไฟล์ SQLite แคช)
แล้วใช้ storage_set ให้โฟลเดอร์เหล่านั้นอยู่บนพื้นที่เก็บไฟล์ถาวร
หลังนำขึ้นแล้ว ทดสอบอัปโหลดไฟล์หนึ่งไฟล์ นำขึ้นซ้ำอีกรอบ แล้วยืนยันว่าไฟล์ยังเปิดได้
ทาง 3: หน้า "อัปโหลดแล้วขึ้นเว็บ" เปิดให้เอง
ถ้าคุณส่งไฟล์ ZIP เองผ่านเมนู อัปโหลดแล้วขึ้นเว็บ (ยังเป็นรุ่น BETA) ระบบอ่านโค้ดแล้วดูว่าแอปเขียนไฟล์ลงโฟลเดอร์ไหน เช่น uploads/ data/ หรือไฟล์ SQLite แล้วเปิดพื้นที่ถาวรให้อัตโนมัติ ไฟล์ที่อยู่ในโฟลเดอร์นั้นใน ZIP (เช่น รูปเดิมหรือไฟล์ฐานข้อมูล SQLite ที่มีข้อมูลแล้ว) ถูกคัดลอกเข้าไปให้ครั้งแรก
ครั้งต่อไปที่ส่ง ZIP ชุดใหม่ ข้อมูลบนเว็บไม่ถูกทับ ถ้าตั้งใจจะใช้ไฟล์ข้อมูลจาก ZIP ชุดใหม่แทนจริง ๆ ให้ติ๊ก ใช้ไฟล์ข้อมูลจากชุดนี้แทนข้อมูลบนเว็บ ก่อนส่ง
กติกาที่ควรรู้ก่อนเลือกขนาด

- ใช้พื้นที่ของแพ็กเกจ ขนาดของพื้นที่ถาวรทุกโปรเจกต์ในบัญชีรวมกันได้ไม่เกินพื้นที่ของแพ็กเกจ (Free 20 MB, Starter 200 MB, Maker 1 GB, Growth 10 GB, Pro 25 GB) และนับแยกจากไฟล์โค้ดที่อัปโหลด
- เลือกได้สูงสุด 80% ของที่ยังว่าง แพ็กเกจ Free จึงได้ราว 16 MB พอสำหรับไฟล์ SQLite หรือรูปไม่กี่สิบรูป
- เพิ่มได้ ลดไม่ได้ เลือกขนาดที่พอดีกับตอนนี้ก่อน แล้วค่อยเพิ่มเมื่อใกล้เต็ม
- ปิดแล้วข้อมูลไม่หาย การปิดหมายถึงเวอร์ชันถัดไปไม่ต่อพื้นที่นี้ ดิสก์เดิมยังถูกเก็บไว้
- นำขึ้นเวอร์ชันใหม่มีช่วงหยุดสั้น ๆ เพราะเวอร์ชันเก่าต้องปล่อยดิสก์ก่อนเวอร์ชันใหม่จะใช้ได้
- คำสั่งและงานตามเวลาก็เห็นไฟล์ชุดเดียวกัน คำสั่งที่รันหลังนำขึ้น (release command) คำสั่งที่สั่งรันครั้งเดียว และงานตามเวลา (cron) เห็นโฟลเดอร์เดียวกับแอป งานล้างไฟล์เก่าหรือย่อรูปจึงทำได้
ถ้าไฟล์ที่ผู้ใช้อัปโหลดสำคัญกับธุรกิจ (เช่น สลิปหรือเอกสารสัญญา) แนะนำแอดออน Backups 99 บาทต่อเดือน ซึ่งสำรองฐานข้อมูลรายวันและสำรองพื้นที่ /bw-data ของทุกโปรเจกต์ให้ด้วย
ทดสอบว่าไฟล์ไม่หายจริง
อย่าเชื่อแค่ว่าอัปโหลดได้ ให้ลองครบรอบแบบนี้หนึ่งครั้ง
- อัปโหลดรูปทดสอบหนึ่งรูปบนเว็บจริง แล้วเปิดดูให้ขึ้น
- นำขึ้นเวอร์ชันใหม่ (แก้ข้อความเล็ก ๆ สักจุดก็ได้)
- เปิดรูปเดิมอีกครั้ง ถ้ายังขึ้นแปลว่าเก็บถูกที่แล้ว
- ลบรูปทดสอบออก
ถ้ารูปหาย ให้ส่งข้อความนี้ให้ AI: "รูปที่อัปโหลดหายหลังนำขึ้นใหม่ ตรวจว่าโค้ดเก็บไฟล์ไว้ที่ไหน แล้วย้ายไปไว้ใต้ /bw-data หรือใช้ storage_set กับโฟลเดอร์นั้น"
คำถามที่พบบ่อย
ข้อมูลในฐานข้อมูลต้องเปิดพื้นที่นี้ด้วยไหม
ไม่ต้อง ฐานข้อมูลที่สร้างในโปรเจกต์ (PostgreSQL, MySQL, MariaDB, MongoDB) เก็บข้อมูลของตัวเองแยกไว้แล้ว พื้นที่นี้มีไว้สำหรับ "ไฟล์" ที่แอปเขียนเอง รวมทั้งไฟล์ SQLite
ใช้ /data หรือ /bw-data ดี
ใช้ /bw-data สำหรับโค้ดใหม่ ทั้งสองชื่อคือโฟลเดอร์เดียวกัน เขียนที่ชื่อหนึ่งก็เห็นอีกชื่อ /data เป็นชื่อเดิมที่ยังใช้ได้ แต่ชื่อนี้ชนกับโฟลเดอร์ของแอปได้ง่าย
ดูหรือดาวน์โหลดไฟล์ใน /bw-data จากคอนโซลได้ไหม
ตอนนี้คอนโซลยังไม่มีหน้าเปิดดูไฟล์ในพื้นที่นี้ แท็บ ไฟล์ แสดงไฟล์โค้ดที่อัปโหลด ถ้าต้องการจัดการไฟล์ของผู้ใช้ ให้ AI ทำหน้าหลังบ้านในแอปสำหรับดูและดาวน์โหลดไฟล์ โดยให้เฉพาะผู้ดูแลเข้าได้
พื้นที่ 16 MB ของแพ็กเกจ Free พอไหม
พอสำหรับแอปทดลอง ไฟล์ SQLite เล็ก ๆ หรือรูปที่ย่อขนาดแล้ว ถ้าเว็บให้คนอัปโหลดรูปจริงจัง ควรใช้แพ็กเกจที่จ่ายเงิน และสั่ง AI ให้ย่อรูปก่อนเก็บ เช่น กว้างไม่เกิน 1,600 px
ลบโปรเจกต์แล้วไฟล์ใน /bw-data จะเป็นยังไง
ไฟล์ในพื้นที่นี้ผูกกับโปรเจกต์ ลบโปรเจกต์แล้วแอปก็ไม่มีที่ให้เปิดไฟล์เหล่านั้นอีก ถ้ามีไฟล์สำคัญ ให้ดึงออกมาเก็บก่อน (เช่น ผ่านหน้าหลังบ้านของแอปที่ทำไว้ในข้อก่อนหน้า) แล้วค่อยลบโปรเจกต์
สรุป
แอปบน BrewInTH เริ่มใหม่จากโค้ดทุกครั้งที่นำขึ้นเวอร์ชันใหม่ ไฟล์ที่ผู้ใช้อัปโหลดจึงต้องอยู่ในพื้นที่เก็บไฟล์ถาวร /bw-data เปิดเองได้ในแท็บ ตั้งค่าแอป ให้ AI ตั้งด้วย storage_set หรือให้หน้า อัปโหลดแล้วขึ้นเว็บ เปิดให้ เลือกขนาดที่พอดีก่อนเพราะลดลงไม่ได้ แล้วทดสอบด้วยการนำขึ้นซ้ำหนึ่งรอบ รูปของผู้ใช้จะไม่หายอีก
