ที่เก็บไฟล์และรูปภาพ (Storage / S3-MinIO)
ภาพรวม
ไฟล์ทุกชิ้นที่ผู้ใช้อัปโหลดผ่าน CMS ผ่าน service ตัวเดียวกันคือ internal/storage.Service
ซึ่งเป็นชั้นห่อของ S3/MinIO ครอบคลุมตั้งแต่รูป rich message, รูป rich menu, รูป hero ของ template,
รูปในหน้า content page, ไฟล์ CSV ของ audience / customer database / import mapping ไปจนถึง avatar ของผู้ใช้
โมดูล internal/modules/storage ไม่มี route ของตัวเอง (RegisterRoutes เป็น no-op)
เพราะใน NestJS เดิมเป็น @Global provider แบบไม่มี controller
โมดูลนี้จึงเป็นเพียง type alias ที่ชี้ไปยัง service ที่แชร์ผ่าน Deps.Storage
Business Flow
- controller ที่รับ
multipart/form-dataแปลงไฟล์ที่อัปโหลดเป็นstorage.Fileซึ่งมีฟิลด์originalName,extension,mimetypeและbufferเลียนแบบMemoryStoredFileของ nestjs-form-data - เรียก method ตามชนิดของงาน
PutTemp/PutTempBuffer— เก็บชั่วคราวก่อนผู้ใช้ยืนยันPutImage/PutImageBuffer— เก็บรูปลงโฟลเดอร์ตามFolderNamePutFile— เก็บไฟล์ทั่วไป เช่น CSV
- ไฟล์ถูกจัดเก็บแยกโฟลเดอร์ตาม root folder ของแต่ละ tenant ผ่าน
GetRootFolder - เมื่อต้องอ่านกลับ
GetPublicUrl/GetPublicFileUrl— URL สาธารณะ ใช้กับไฟล์ที่ต้องส่งเข้า LINE ซึ่งต้องเข้าถึงได้จากภายนอกGeneratePresignedUrl— URL แบบมีวันหมดอายุ สำหรับไฟล์ที่ไม่ควรเปิดสาธารณะGetImage/GetPathUrl— ดึงไฟล์และแปลง path
- งานอื่น ๆ ได้แก่
DeleteObject,IsFileExistและCopyObjectFromPublicUrlโดยตัวสุดท้ายใช้ตอน duplicate content หรือ clone rich menu ซึ่งต้องคัดลอกรูปจาก URL เดิม - ไฟล์ CSV ที่เก็บไว้จะถูกอ่านต่อโดย CSV Engine เมื่อต้องแบ่งหน้ารายชื่อ LINE user
ไฟล์และฟังก์ชันหลัก
| ไฟล์ | บทบาท |
|---|---|
internal/storage/storage.go | Service ตัวจริง — port ของ src/storage/storage.service.ts |
internal/storage/image.go | จัดการรูปภาพ เช่น validate ชนิดไฟล์และแปลงชื่อไฟล์ |
internal/modules/storage/service.go | type alias ของ Service, File, StorageType, FolderName, ImageFileType, RootFolder |
internal/modules/storage/controller.go | RegisterRoutes เป็น no-op |
Method ทั้งชุด: GetPublicUrl, GetPathUrl, GetImage, PutTemp, PutImage, PutTempBuffer,
PutImageBuffer, DeleteObject, CopyObjectFromPublicUrl, IsFileExist, GetRootFolder,
PutFile, GetPublicFileUrl, GeneratePresignedUrl
Endpoint ที่อัปโหลดไฟล์จริง — อยู่ในโมดูลอื่น แต่ปลายทางลงมาที่ service นี้ทั้งหมด
| Route | โมดูล |
|---|---|
POST /api/content-pages/upload-image | Content Page |
POST /api/menu-builder/upload-image | Menu Builder |
POST /api/template-message/upload-image | Template Message |
POST /api/rich-message (form-data) | Rich Message |
POST /api/rich-menu (form-data) | Rich Menu |
POST /api/friend-track/:id/refs/upload | Friend Track |
POST /api/customer-database และ /preview | Customer Database |
POST /api/import-mapping/upload | Import Mapping |
POST /api/line-users/import-all-friends | LINE User Management |
POST /api/user (avatar) | User Management |
จุดเชื่อมต่อกับ Service อื่น
- Permission — ไม่มี route ของตัวเอง สิทธิ์จึงถูกบังคับที่ endpoint ของโมดูลผู้เรียก
- Infrastructure — ใช้ S3 หรือ MinIO ตามค่า
StorageTypeซึ่งตั้งจาก environment ในinternal/config/config.go - ผู้บริโภค —
Deps.Storageถูก inject ให้ทุกโมดูล และDeps.CSVEngineก็รับ storage ตัวนี้เข้าไปด้วย