จัดเก็บรูปภาพลงฐานข้อมูลหรือจัดเก็บเป็นไฟล์ดีกว่ากัน

มีคำถามบ่อยๆถึงวิธีการจัดเก็บรูปภาพบน Server ว่าใช้วิธีไหนถึงจะเหมาะสม ระหว่างการจัดเก็บลงฐานข้อมูลและการจัดเก็บเป็นไฟล์

การเก็บข้อมูลรูปภาพลงฐานข้อมูล อาศัยการเก็บข้อมูลเป็น blob ลงฐานข้อมูล (blob ถูกจัดเก็บเป็นไบนารี่)
$image = base64_encode(file_get_contents('/path/to/file.png'));
  1. อ่านไฟล์ด้วย file_get_contents() ได้ข้อมูลของไฟล์ออกมา (ใช้ฟังก์ชั่นอื่นก็ได้ที่สามารถอ่านเนื้อหาของไฟล์ออกมาได้)
  2. เข้ารหัสเนื้อหาด้วยที่อ่านได้ด้วย base64 ซึ่งจริงๆแล้วเราไม่ต้องเข้ารหัสก็ได้ แต่เหตุผลที่ควรจะเข้ารหัส (เป็น base64) เนื่องจาก
    • ด้านความปลอดภัย การจัดเก็บเนื้อหาของไฟล์ตรงๆ อาจมีการแอบแทรกคำสั่งที่ไม่พึงประสงค์ลงในไฟล์รูปภาพที่จัดเก็บได้ ซึ่งอาจทำให้การ insert ข้อมูลมีปัญหา
    • tag IMG รองรับข้อมูลประเภท base64 อยู่แล้ว ทำให้การนำข้อมูลรูปภาพออกมาใช้ไม่ต้องเสียเวลาแปลงอีก
  3. จัดเก็บข้อมูลที่เข้ารหัสแล้วลงฐานข้อมูล
ส่วนการนำข้อมูลที่จัดเก็บไว้มาแสดงผลก็แสนง่าย
<img src="data:image/png;base64,'.$image.'">

image/png เปลี่ยนไปตาม mime ของข้อมูลรูปภาพที่จัดเก็บไว้
จริงอยู่ว่าการจัดเก็บข้อมูลรูปภาพลงฐานข้อมูลโดยตรง จะทำให้เราสามารถจัดการกับข้อมูลและรูปภาพได้ง่าย เช่นการลบข้อมูล จะสามารถลบรูปภาพออกไปด้วยทันทีเมื่อมีการลบเร็คคอร์ด แต่การเก็บข้อมูลรูปภาพลงบนฐานข้อมูลโดยตรงก็มีข้อเสียที่สำคัญกว่า 
  • ไฟล์รูปภาพมักมีขนาดใหญ่ อาจตั้งแต่หลายร้อยไบท์ ไปจนถึงระดับเม็กกะไบท์ ซึ่งถ้ามีหลายๆเร็คคอร์ด อาจทำให้ได้ Database ที่ใหญ่มาก (นิยมเรียกว่า Database บวม) ซึ่งส่งผลให้ Database ทำงานได้ช้า
  • การเข้ารหัสแบบ Base64 ยังทำให้ได้ข้อมูลที่มีขนาดใหญ่กว่าข้อมูลต้นฉบับอีก (เนื่องจากต้องแปลงข้อมูลไบนารี่ให้เป็นสตริงค์ที่สามารถอ่านได้)
  • การ query รูปภาพจากฐานข้อมูล ต้องอาศัยการทำงานของฐานข้อมูล ซึ่งเป็นการเพิ่มภาระให้กับ Server ในการส่งข้อมูลกลับมา ในขณะที่การเก็บเป็นไฟล์ สามารถใช้ความสามารถของ Server (เช่น NGINX) ในการส่งไฟล์กลับมาซึ่งมีประสิทธิภาพมากกว่าหลายเท่าตัว
จริงๆแล้ว จะเห็นว่าเราแทบจะไม่สามารถหาความดีงามของการเก็บรูปภาพลงฐานข้อมูลได้เลย นอกจากการลบข้อมูล ซึ่งในความเป็นจริงแล้วในหนึ่งหน้า อาจประกอบด้วยรูปภาพมากกว่า 1 รูป กลับจะทำให้การจัดเก็บข้อมูลรูปภาพลงฐานข้อมูลยุ่งยากมากขึ้นไปอีกด้วย ดังนั้นวิธีที่เหมาะสมจึงมีเพียงวิธีเดียว คือการจัดเก็บรูปภาพเป็นไฟล์บน Server และจัดเก็บ file path ของรูปภาพลงบนฐานข้อมูลแทน

มีคำถามเพิ่มเติมว่า แล้วการเก็บ file path ของรูปภาพควรเก็บเฉพาะชื่อไฟล์ หรือเก็บแบบ fullpath ดี
  • การเก็บแบบ fullpath ไม่เหมาะสมเป็นอย่างยิ่ง เพราะหากมีการเปลี่ยนแปลงหรือย้าย Server อาจจะทำให้หาไฟล์ไม่เจอทันที (เนื่องจากแต่ละ Server อาจมีที่อยู่ไม่ตรงกัน)
  • การเก็บแบบอ้างอิงจาก root ของ server มักใช้ในกรณีที่ ที่อยู่ของไฟล์ไม่แน่นอน
  • เก็บเฉพาะชื่อไฟล์ (ส่วนตัวใช้วิธีนี้เป็นส่วนใหญ่) เนื่องจากผมจะออกแบบโครงสร้างของเว็บไซต์ให้การอัปโหลดไปรวมอยู่ที่เดียว (เช่น images/) ข้อดีก็คือ เราสามารถควบคุมได้ง่าย (เช่นการป้องกัน hotlink) และข้อดีที่ดีกว่าคือข้อมูลที่จัดเก็บใน Daatabse มีขนาดเล็กที่สุด
ผู้เขียน goragod โพสต์เมื่อ 09 พ.ค. 2561 เปิดดู 23,815 ป้ายกำกับ PHP
^