แก้ไขปัญหา PHP อัปโหลดไฟล์ขนาดใหญ่ บนเว็บเซิร์ฟเวอร์ nginx

ค่าคอนฟิกในโปรแกรมที่ติดตั้งมาส่วนใหญ่ โดยดีฟอลต์จะถูกตั้งค่ามาให้สามารถรันและใช้งานบนเครื่องทั่วไปได้ ทำให้บางครั้งเมื่อมีปริมาณการใช้งานเพิ่มมากขึ้น อาจจะมีปัญหาในการใช้งาน

ลองมาดูวิธีการตรวจสอบ และแก้ไขปัญหาการอัปโหลดไฟล์ขนาดใหญ่ด้วย PHP ที่รันโหมด FPM ทำงานร่วมกับ nginx เป็นเว็บเซิร์ฟเวอร์กัน ว่าจะต้องแก้ไขคอนฟิกอะไรบ้าง เพื่อให้สามารถอัปโหดลไฟล์ขนาดใหญ่ตามที่เราต้องการได้

ในที่นี้จะใช้โปรแกรม WordPress 4.8.2 ทดสอบบน Ubuntu 16.04 ซึ่งถ้าไม่แก้ไขคอนฟิก จะติดปัญหาการอัปโหลดไฟล์ขนาดใหญ่ เพราะโปรแกรมนี้ถูกพัฒนาด้วยภาษา PHP

ตัวอย่างการทดสอบอัปโหลดไฟล์ขนาดใหญ่ (ประมาณ 64M) ในหน้าจอ Insert Media ของ WordPress

ขึ้นข้อความแถบสีแดงว่า exceeds the maximum upload size for this size

สังเกตข้อความด้านล่างแสดง Maximum upload file size: 2MB

ค่าคอนฟิกที่เป็นตัวกำหนดขนาดไฟล์สูงสุดที่อัปโหลดได้ใน PHP คือ upload_max_filesize โดยดีฟอลต์จากการติดตั้ง จะถูกจำกัดให้สามารถอัปโหลดไฟล์ได้แค่ 2M เท่านั้น

และเนื่องจากการอัปโหลดไฟล์ใน PHP จะเป็นการส่งข้อมูลโดยใช้เมธอดแบบ POST ดังนั้นต้องแก้ไขค่าคอนฟิก post_max_size ด้วย เพราะเป็นค่าที่กำหนดขนาดข้อมูลสูงสุดที่สามารถส่งข้อมูลแบบ POST ได้

ไฟล์คอนฟิก PHP ที่รันโหมด FPM บน Ubuntu 16.04 คือ /etc/php/7.0/fpm/php.ini

เช่นถ้าเราต้องการให้สามารถอัปโหลดไฟล์ได้สูงสุด 128MB เราต้องแก้ไขค่าคอนฟิกทั้งสองค่าให้เป็น 128M เพื่อให้สามารถอัปโหลดไฟล์ได้ขนาดสูงสุด ตามที่เราต้องการได้

alice@u16:~$ sudo vi /etc/php/7.0/fpm/php.ini

; Maximum size of POST data that PHP will accept.
; Its value may be 0 to disable the limit. It is ignored if POST data reading
; is disabled through enable_post_data_reading.
; http://php.net/post-max-size
post_max_size = 128M

; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
upload_max_filesize = 128M

ใช้คำสั่ง systemctl restart เพื่อรีสตาร์ตเซอร์วิส PHP ที่รันโหมด FPM

alice@u16:~$ sudo systemctl restart php7.0-fpm

รีโหลดหน้าเว็บ WordPress ใหม่ แล้วลองเข้าหน้า Insert Media อีกครั้ง

สังเกตข้อความด้านล่างจะเปลี่ยนเป็น Maximum upload file size: 128MB

กดปุ่ม Select Files ทดลองอัปโหลดไฟล์ขนาดใหญ่อีกครั้ง

ก็ยังไม่สามารถอัปโหลดได้ แต่ข้อความ error ที่แสดงจะเปลี่ยนไป ขึ้น HTTP error แทน

ถึงแม้เราแก้ไขค่าคอนฟิกเพื่อให้อัปโหลดไฟล์ขนาดใหญ่ใน PHP ไปแล้ว แต่ตอนนี้ยังมีปัญหาอีกส่วนหนึ่งคือเว็บเซิร์ฟเวอร์ ซึ่งในที่นี้เราใช้ nginx

เวลาที่เราคิดว่าน่าจะเป็นปัญหาที่เว็บเซิร์ฟเวอร์ nginx แนะนำให้ลองดูไฟล์ /var/log/nginx/error.log

อย่างในปัญหานี้ ในไฟล์ error.log แสดงข้อความ client intended to send too large body

alice@u16:~$ tail /var/log/nginx/error.log

2017/10/19 17:22:44 [error] 3162#3162: *1 client intended to send too large body: 66430314 bytes, client: 192.168.1.2, server: _, request: "POST /wp-admin/async-upload.php HTTP/1.1", host: "192.168.1.1", referrer: "http://192.168.1.1/wp-admin/post-new.php"

เว็บเซิร์ฟเวอร์ nginx จะมีค่าคอนฟิกดีฟอลต์ กำหนดขนาดข้อมูลสูงสุดที่ client จะส่งได้ ซึ่งดีฟอลต์จะกำหนดไว้แค่ 1m เท่านั้น

จากหน้าเว็บของ nginx แสดงการใช้งานค่าคอนฟิก Module ngx_http_core_module

Syntax: client_max_body_size size;
Default: client_max_body_size 1m;
Context: http, server, location

ทดลองเพิ่มค่าคอนฟิก client_max_body_size ภายใต้หัวข้อคอนฟิก http โดยกำหนดไว้ที่ 128m

alice@u16:~$ sudo vi /etc/nginx/nginx.conf

http {
    ....
    client_max_body_size 128m;

รีสตาร์ตเว็บเซิร์ฟเวอร์ nginx

alice@u16:~$ sudo systemctl restart nginx

ทดลองอัปโหลดไฟล์ใน WordPress อีกครั้ง

ตอนนี้ขึ้นอีก error คือ Unable to create directory wp-content/uploads ซึ่งจริงๆ แล้วไม่เกี่ยวกับปัญหาขนาดไฟล์ใหญ่ หรือค่าคอนฟิกแล้วที่เพิ่งแก้ไขไป แต่เป็นเพราะไฟล์ที่ถูกอัปโหลดไป ไม่สามารถบันทึกบนเว็บเซิร์ฟเวอร์ได้ เป็นปัญหาเรื่อง permission

การแก้ไขปัญหานี้ ต้องสร้างไดเรคทอรี uploads และตั้งค่า permission เป็น 777 เพื่อให้เว็บเซิร์ฟเวอร์สามารถเขียนไฟล์ในนี้ได้

alice@u16:~$ cd /var/www/html/wordpress/wp-content/
alice@u16:/var/www/html/wordpress/wp-content$ mkdir uploads
alice@u16:/var/www/html/wordpress/wp-content$ chmod 777 uploads/
alice@u16:/var/www/html/wordpress/wp-content$

ทดลองอัปโหลดไฟล์ใน WordPress อีกครั้ง ตอนนี้น่าจะอัปโหลดไฟล์ได้แล้ว

ตัวอย่างไฟล์ที่บันทึกบนเซิร์ฟเวอร์ได้

alice@u16:/var/www/html/wordpress/wp-content/uploads/2017/10$ ls -l 
-rw-rw-rw- 1 www-data www-data  67449725 Oct 19 18:28 test.mp4

ในที่นี้ใช้ WordPress ในการทดสอบ แต่โปรแกรมอื่นๆ ที่ถูกพัฒนาด้วยภาษา PHP ก็น่าจะเจอปัญหาคล้ายๆ กัน ลองนำไปใช้แก้ปัญหากันดูครับ

ข้อมูลอ้างอิง

Leave a Reply

Your email address will not be published.