สร้างระบบ Resize รูปให้ LINE Chatbot ด้วย Firebase Extensions
การแสดงผลรูป original ขนาดใหญ่ที่ผู้ใช้อัพโหลดเข้ามานั้น มักส่งผลทำให้ระบบของเราตอบสนองได้ช้าลง ใช้งาน bandwidth เพิ่มขึ้น และเป็นเหตุที่ทำให้ cost ของการให้บริการสูงขึ้นด้วย โดยเฉพาะการแสดงผลที่ไม่จำเป็นต้องใช้รูปต้นฉบับ เช่นการแสดง thumbnails ของสินค้าเป็นต้น
การย่อรูป หรือ Image resizing
เป็นกระบวนการที่นักพัฒนาเลือกทำเพื่อลดต้นทุนที่จะเกิดขึ้น เพราะมันคุ้มกว่า หากเทียบกับค่าใช้จ่ายของ storage ที่เสียไป และเพื่อให้เห็นภาพเรามาดูตัวอย่างกัน โดยผมจะสมมติว่ารูปที่ผู้ใช้อัพโหลดเข้ามามีขนาด 500KB และมีคนเปิดดูรูป 1,000,000 ครั้ง(แบบไม่ติด cache)
- Original: 500 x 1,000,000 ≈ 500,000 MB
- Resize: 50 x 1,000,000 ≈ 50,000MB
จากการเปรียบเทียบจะเห็นว่า รูปที่ resize แล้วจะสามารถลดการใช้ bandwidth ได้ถึง 10 เท่า ซึ่งถ้ายิ่งคนเปิดดูเยอะก็จะยิ่งประหยัด ในขณะที่พื้นที่ จะเพิ่มขึ้นเพียง 50KB เท่านั้น
อีกเรื่องที่เราควรพิจารณาก่อนการพัฒนาระบบ Image resizing ขึ้นมาก็คือ เราควรให้ระบบนี้อยู่ใน front-end หรือ back-end ดี? ซึ่งโจทย์ข้อนี้มันมี trade-off ของมันอยู่ แต่ส่วนตัวผมเลือกทำที่ back-end ด้วยเหตุผล
- พัฒนาครั้งเดียวใช้ได้ทุกแพลทฟอร์ม
- รูปที่ได้จะมีมาตรฐานและคุณภาพเดียวกัน
- ใช้ทรัพยากรของ client น้อยกว่า
เกริ่นมาซะยาวเลย เข้าเรื่องเลยละกัน บทความนี้ผมจะพาทุกคนไปพัฒนาระบบย่อรูปให้กับ LINE Chatbot ด้วย Firebase Extenstions ผู้ช่วยในการย่อรูป ที่สายย่อต้องชอบ เพราะคุณไม่จำเป็นต้อง setup ตัว storage เอง และไม่ต้องเขียนโปรแกรมในส่วนของการย่อรูปเอง นั่นก็หมายความว่าคุณมีโอกาสจะเป็น Harry Potter ได้ เพราะคุณจะสามารถเสกของออกมาได้ในเวลาอันสั้นนั่นเอง 555+
ขั้นตอนในการพัฒนา
- เตรียม LINE Chatbot ที่พัฒนาด้วย Cloud Functions for Firebase
- พัฒนาระบบอัพโหลดรูปขึ้น Cloud Storage for Firebase
- ย่อรูปด้วย Firebase Extensions
1. เตรียม LINE Chatbot ที่พัฒนาด้วย Cloud Functions for Firebase
สำหรับใครที่ยังไม่เคยพัฒนา LINE Chatbot ด้วย Cloud Functions for Firebase ให้ทำตามขั้นตอนของบทความด้านล่างนี้(ข้อ 1–3 ก็พอ) แต่หากใครมีประสบการณ์ตรงนี้แล้ว ข้ามไปขั้นตอนที่ 2 ได้เลย
หมายเหตุ: เนื่องจากการพัฒนา LINE Chatbot ด้วย Cloud Functions คุณจำเป็นต้อง request APIs นอก Google domain ทำให้คุณต้องเปลี่ยนแพลนการใช้งานจาก Spark ไปเป็น Blaze แต่ข้อดีคือคุณจะได้โควต้าฟรีเพิ่มขึ้นใน Blaze แบบทวีคูณ
2. พัฒนาระบบอัพโหลดรูปขึ้น Cloud Storage for Firebase
ในโฟลเดอร์ functions ของโปรเจคที่เราได้เตรียมไว้(ขั้นตอนที่ 1) ให้เปิดไฟล์ package.json ขึ้นมา แล้วเพิ่ม dependency ชื่อ uuid-v4 เข้าไป เนื่องจากเราจะใช้มันสร้าง public url ของไฟล์ที่อัพโหลดขึ้น Cloud Storage ในลำดับต่อไป
"dependencies": {
"firebase-admin": "^8.12.1",
"firebase-functions": "^3.6.1",
"request": "^2.88.2",
"request-promise": "^4.2.5",
"uuid-v4": "^0.1.0"
}
ถัดไปเปิดไฟล์ index.js ขึ้นมา แล้ว import ตัว firebase-admin เข้ามาพร้อม initialize ตามด้วย dependencies สำหรับจัดการไฟล์
จากนั้นสร้างฟังก์ชันใหม่ชื่อ uploadPhoto โดยภายในฟังก์ชันให้เขียนเงื่อนไขเพื่อรับ webhook event จาก LINE ซึ่งเราจะสนใจเฉพาะกรณีที่ผู้ใช้อัพโหลดรูปเข้ามา
ต่อมาก็สร้างฟังก์ชัน upload() โดยฟังก์ชันนี้จะทำหน้าที่ในการดาวน์โหลด binary ออกมาจาก LINE และอัพโหลดไปยัง Cloud Storage for Firebase บริการฝากไฟล์ที่ให้พื้นที่ฟรี 5 GB
หมายเหตุ: ปกติการอัพโหลดไฟล์ขึ้น Cloud Storage ด้วย Firebase Admin ไฟล์จะได้สถานะเป็น private ซึ่งการเพิ่ม firebaseStorageDownloadTokens ที่มีค่าเป็น uuid นี้ เป็นเทคนิคในการทำให้เราได้ public url ออกมา
สุดท้ายก็สร้างฟังก์ชัน reply() เพื่อส่ง URL ที่ได้จากการอัพโหลดกลับไปยังห้องแชท
3. ย่อรูปด้วย Firebase Extensions
Firebase Extensions เป็นบริการที่ช่วยลดเวลาในการพัฒนาฟังก์ชันต่างๆ ที่เรามักจะต้องพัฒนาขึ้นมาใช้เองใน Firebase โดยนักพัฒนาเพียงแค่ติดตั้ง extension ที่ต้องการ ก็จะสามารถใช้งานได้ทันที(ประมาณต้มมาม่ากิน) ซึ่งการย่อรูปก็เป็นหนึ่งในบริการดังกล่าว
เริ่มจากเข้าไปที่ หน้ารวม Extensions แล้วเลือก Resize Images
เมื่อกดปุ่ม Install แล้ว ระบบจะพาไปหน้าที่ให้เลือกโปรเจค ก็ให้เราเลือกโปรเจคเดียวกันกับที่สร้าง LINE Chatbot ไว้ จากนั้นจะเข้าสู่หน้ารายละเอียดการติดตั้ง
โดยขั้นตอนการติดตั้งส่วนที่ 1 และ 2 จะเป็นรายละเอียดว่าจะเปิดใช้ API อะไรบ้าง และขอสิทธิ์การเข้าถึงของ extension ที่จะติดตั้งเป็นอย่างไร อ่านเสร็จก็กด Next ไป
ส่วนที่ 3 คือส่วนที่ให้เราตั้งค่าต่างๆ โดยจุดที่น่าสนใจมีดังนี้
- Location: เลือก data center ที่จะโฮสฟังก์ชันตัวนี้
- Size: ระบุขนาด WxH ที่ต้องการย่อในหน่วย pixel เช่น 200x200 โดยการ resize จะรักษา ratio ให้เราอัตโนมัติ และในกรณีที่ต้องการย่อรูปหลายขนาด ก็สามารถระบุเป็น 200x200,320x320 ได้
- Deletion: ต้องการลบไฟล์ต้นฉบับไหม
- Cloud Storage path: ต้องการสร้าง path เพื่อเก็บรูปที่ย่อไหม โดยถ้าปล่อยว่าง รูปที่ย่อก็จะถูกสร้างที่ level เดียวกับไฟล์ต้นฉบับ
การติดตั้งจะใช้เวลาประมาณ 3–5 นาที ซึ่งระหว่างนี้ผมจะให้ทุกคนกลับไปแก้โค้ดที่ฟังก์ชัน upload() ในไฟล์ index.js กันอีกหน่อย เพราะผมต้องการเปลี่ยนการ return จาก url รูปต้นฉบับ ไปเป็น object ที่ประกอบไปด้วย url ของทั้งรูปต้นฉบับและรูปที่ถูกย่อ
หมายเหตุ: รูปแบบของ thumb url จะขึ้นอยู่กับ size และ path ที่เราตั้งค่าในส่วนที่ 3
ส่วนสุดท้ายก็เปลี่ยนการ reply ในฟังก์ชัน uploadPhoto จาก text ธรรมดา ให้กลายเป็น Flex Message ซะหน่อย ก็จะได้โค้ดทั้งหมดเต็มๆแบบนี้
สรุป
เป็นอย่างไรกันบ้างครับ เร็วใช่มะ สำหรับวิธีพัฒนาระบบย่อรูปที่ผมมาแชร์ เอาจริงๆถ้าได้วางแผนมา แล้วลงมือโค้ดเลย คงไม่เกิน 3 ชม.เสร็จ ซึ่งสมัยก่อนหากผมต้องพัฒนาระบบนี้ขึ้น production คงต้องใช้เวลาตั้งแต่คิด เตรียม server และเขียนโค้ดอีกเป็นวันๆ และนอกจากการพัฒนาระบบย่อรูปให้ Chatbot แล้ว นักพัฒนายังสามารถนำมันไปประยุกต์กับแพลทฟอร์มอื่นๆอย่าง iOS, Android, Web และ Game ได้อีก อย่าลืมกลับไปลองเล่นกันนะครับ
และเพื่อที่คุณจะไม่พลาดบทความใหม่ๆจากทั้ง LINE Developers Thailand และ Firebase Thailand ก็อย่าลืมกด Follow ตัว Publication กันด้วยน้า วันนี้ลาไปก่อน แล้วพบกันใหม่บทความหน้า สวัสดีคร้าบ