ข้ามไปยังเนื้อหา
ข้อผิดพลาดและการล่ม

WordPress ขึ้น "HTTP error" ตอนอัพโหลดรูป: ผังตัดสินใจที่หาต้นเหตุเจอจริง

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

เผยแพร่แล้ว

“HTTP error” ไม่ใช่สาเหตุ มันคือการที่ตัวอัพโหลดสื่อยอมรับว่าส่งไฟล์ไปที่เซิร์ฟเวอร์แล้ว แต่ได้คำตอบกลับมาแบบที่ตีความเป็นความสำเร็จไม่ได้ และมีความล้มเหลวอย่างน้อยหกแบบที่ไม่เกี่ยวกันเลย ซึ่งให้ข้อความสามคำเดียวกันนี้ การเดาสุ่มระหว่างหกแบบนั้นคือเหตุผลที่หลายคนเสียเวลาทั้งบ่ายไปกับการเพิ่ม upload_max_filesize บนเว็บที่ปัญหาจริงคือกฎไฟร์วอลล์

หน้า Upload Media ของ WordPress มีประกาศสีแดงว่า Unexpected response from the server. The file may have been uploaded successfully.
ความล้มเหลวแบบเดียวกัน แต่ใช้ถ้อยคำใหม่กว่า เราทำให้เซิร์ฟเวอร์ตอบการอัปโหลดด้วย 403 และ WordPress 7.1.4 แสดงข้อความนี้แทน “HTTP error” วิธีตรวจสอบด้านล่างยังใช้ได้เหมือนเดิม

ทางออกที่เร็วที่สุดคือการสังเกตเพียงจุดเดียว ที่แยกหกสาเหตุออกเป็นสองกลุ่ม แล้วตรวจเพิ่มอีกกิ่งละหนึ่งอย่าง

ก่อนอื่น: อ่านคำตอบตัวจริง

เปิดเครื่องมือนักพัฒนาในเบราว์เซอร์ ไปที่แท็บ Network แล้วอัพโหลดไฟล์อีกครั้ง จับตาดูคำขอที่ยิงไปยัง async-upload.php สิ่งที่ตอบกลับมาคือผลวินิจฉัยของคุณ

สิ่งที่คุณเห็นความหมายไปที่
403 หรือ 406 เนื้อหาเป็น HTMLไฟร์วอลล์หรือ mod_security ปฏิเสธคำขอกิ่ง A
500 หรือคำตอบเปล่า หรือเนื้อหาขาดกลางคันPHP พังหรือหน่วยความจำหมดกลางทางกิ่ง B
413เนื้อหาคำขอเกินลิมิตของเซิร์ฟเวอร์กิ่ง C
200 แต่เนื้อหาไม่ใช่ JSON ที่สะอาดปลั๊กอินหรือธีมพิมพ์อะไรออกมาก่อนคำตอบกิ่ง D
คำขอไม่จบสักที หรือหมดเวลาลิมิตเวลาประมวลผล มักเกิดกับไฟล์ใหญ่กิ่ง B

การมองครั้งเดียวนั้นตัดคำแนะนำส่วนใหญ่บนอินเทอร์เน็ตออกไปให้คุณเลย ถ้าเข้าเครื่องมือในเบราว์เซอร์ไม่ได้ ให้เปิดการบันทึก log ใน wp-config.php ก่อน:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );

ทำให้เกิดปัญหาซ้ำ แล้วเปิดอ่าน wp-content/debug.log บรรทัด fatal error จะระบุกิ่งให้ตรง ๆ ถ้าบรรทัดนั้นอ่านยาก ลองวางลงใน ตัวถอดรหัส error log ซึ่งจับคู่ลายเซ็นของ fatal error ที่พบบ่อยเข้ากับสิ่งที่พังจริง

กิ่ง A — กฎของไฟร์วอลล์หรือ mod_security

403 ที่มีหน้า HTML อยู่ในเนื้อหา แปลว่าคำขอนั้นไปไม่ถึง WordPress เลย มีบางอย่างที่ยืนอยู่ข้างหน้า ไม่ว่าจะเป็น mod_security, Cloudflare, Wordfence, Sucuri หรือชุดกฎของโฮสต์เอง ตัดสินว่าคำขอ POST นั้นดูอันตราย

วิธีตรวจ: ปิดปลั๊กอินความปลอดภัยชั่วคราว แล้วอัพโหลดใหม่ ถ้าไม่มีอะไรเปลี่ยน แปลว่ากฎอยู่ที่ระดับเซิร์ฟเวอร์ และคุณต้องให้โฮสต์เข้าไปดู mod_security audit log ที่เวลาซึ่งการอัพโหลดล้มเหลว เขาจะปลดล็อกกฎเฉพาะรหัสนั้นให้ได้

พูดกันตรง ๆ เรื่องคำแนะนำที่คุณจะเจอในหัวข้อนี้ สคริปต์ที่บอกให้คุณวางบรรทัดนี้ลงใน .htaccess:

SecFilterEngine Off
SecFilterScanPOST Off

ใช้กับ mod_security 1.x ซึ่งแทบสูญพันธุ์ไปแล้ว บนเซิร์ฟเวอร์สมัยใหม่ คำสั่งพวกนี้ไม่ทำอะไรเลย หรือไม่ก็โยน 500 ออกมาทำให้เว็บแย่ลงกว่าเดิม mod_security รุ่นใหม่ใช้ SecRuleEngine และโฮสต์แบบ managed ส่วนใหญ่ก็บล็อกการเขียนทับค่านี้รายไดเรกทอรีอยู่แล้ว ถามโฮสต์เถอะ อย่าก๊อบวาง

กิ่ง B — ลิมิตหน่วยความจำหรือเวลาประมวลผลของ PHP

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

ทำไมต้องเป็นรูปภาพโดยเฉพาะ เพราะ WordPress ไม่ได้แค่เก็บไฟล์ แต่คลายมันออกเป็นพิกเซลดิบเพื่อสร้างขนาดกลางทางทุกขนาด ทั้ง medium_large ทุกขนาดที่ลงทะเบียนไว้ด้วย add_image_size รวมถึง woocommerce_thumbnail ถ้าคุณเปิดร้านค้า บวกสำเนา -scaled อีกหนึ่งชุดถ้าภาพใหญ่เกิน big_image_size_threshold ไฟล์ JPEG 12 ล้านพิกเซลมีขนาดไม่กี่ MB บนดิสก์ แต่กินราว 48MB ในหน่วยความจำ ก่อนจะนับบัฟเฟอร์สำหรับย่อภาพด้วยซ้ำ ลิมิต 128MB จึงหมดไปอย่างรวดเร็ว

เพิ่มค่าใน wp-config.php เหนือบรรทัด “stop editing”:

define( 'WP_MEMORY_LIMIT', '256M' );
define( 'WP_MAX_MEMORY_LIMIT', '512M' );

ต้นทุนจริงคือ WP_MEMORY_LIMIT ไม่สามารถเกินค่าที่ PHP อนุญาตได้ ถ้าโฮสต์ล็อก memory_limit ไว้ที่ 128M ค่าคงที่นี้ก็เป็นแค่ของประดับ ตรวจค่าจริงได้ที่ Tools → Site Health → Info → Server ไม่ใช่จากสิ่งที่คุณพิมพ์ลงไป ถ้าลิมิตของ PHP เองคือเพดาน มีแต่โฮสต์เท่านั้นที่ขยับได้

กิ่ง C — ลิมิตขนาดไฟล์และขนาดคำขอ

ดูตัวเลขจริงได้ที่ Tools → Site Health → Info → Media Handling มีสองค่าที่สำคัญ แต่คนมักเปลี่ยนแค่ค่าเดียว

  • upload_max_filesize — เพดานของไฟล์เดี่ยว
  • post_max_size — เพดานของเนื้อหาคำขอ ทั้งก้อน
หน้า Site Health Info ของ WordPress ส่วน Media Handling มีแถว max size of post data allowed และ max size of an uploaded file
จุดที่อ่านตัวเลขทั้งสองได้ ค่าที่เห็นนี้เป็นของเซิร์ฟเวอร์ทดสอบของเรา ของคุณจะต่างออกไป

ถ้าคำขอ POST ทั้งก้อนเกิน post_max_size PHP จะทิ้งคำขอนั้นก่อนที่ WordPress จะได้รันโค้ดสักบรรทัด จึงไม่มีอะไรให้ตอบกลับ ตัวอัพโหลดได้คำตอบที่ตีความไม่ได้และขึ้นว่า “HTTP error” ค่า post_max_size ควรใหญ่กว่า upload_max_filesize อย่างสบาย ๆ เสมอ

มีข้อสังเกตที่ควรรู้ เมื่อไฟล์เกินแค่ upload_max_filesize ตัวอัพโหลดมักดักได้ตั้งแต่ในเบราว์เซอร์และบอกว่าไฟล์เกินขนาดสูงสุดที่อัพโหลดได้ ซึ่งเป็นข้อความที่ชัดเจนกว่า ดังนั้น “HTTP error” เปล่า ๆ จึงชี้ไปที่ post_max_size หรือกิ่ง B บ่อยกว่าค่าที่ทุกคนรีบเพิ่มเป็นอย่างแรก

จะแก้ที่ไหนขึ้นอยู่กับสแตกของคุณ บน Apache ที่ใช้ mod_php ใช้ .htaccess ได้:

php_value upload_max_filesize 64M
php_value post_max_size 128M

บน PHP-FPM, LiteSpeed หรือ NGINX ซึ่งคือโฮสติ้งสมัยใหม่ส่วนใหญ่ บรรทัดพวกนี้ไม่ทำอะไรเลย และอาจโยน 500 ออกมา ให้ใช้แผงตั้งค่า PHP ของโฮสต์ หรือไฟล์ .user.ini แทน NGINX ยังบังคับใช้ client_max_body_size ของตัวเองด้วย ซึ่งมีแต่โฮสต์เท่านั้นที่เพิ่มให้ได้

กิ่ง D — ไลบรารีจัดการภาพ (Imagick กับ GD)

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

บังคับใช้ GD เพื่อทดสอบสมมติฐาน:

add_filter( 'wp_image_editors', function ( $editors ) {
    return array( 'WP_Image_Editor_GD' );
} );

วางไว้ใน functions.php หรือทำเป็น mu-plugin เล็ก ๆ ลองอัพโหลดใหม่ แล้วเอาออกถ้าไม่มีอะไรเปลี่ยน

ข้อแลกเปลี่ยนตามจริง: GD ไม่ได้ดีกว่าเสมอไป มันเก็บบิตแมปที่คลายแล้วทั้งหมดไว้ในหน่วยความจำของ PHP ดังนั้นกับไฟล์ขนาดใหญ่มาก มันอาจชน memory_limit ในจุดที่ ImageMagick ซึ่งทำงานบางส่วนนอกการจองหน่วยความจำของ PHP ทำสำเร็จได้ การสลับจึงอาจเป็นการแลกความล้มเหลวแบบหนึ่งกับอีกแบบหนึ่ง ให้ถือว่ามันเป็นเครื่องมือวินิจฉัยก่อน แล้วค่อยเป็นทางแก้

กิ่ง E — สิทธิ์ของไดเรกทอรี uploads

พบน้อยบนโฮสต์แบบ managed แต่พบบ่อยหลังการย้ายเว็บหรือย้ายเซิร์ฟเวอร์ด้วยมือ ถ้า wp-content/uploads ไม่เปิดให้ผู้ใช้ของเว็บเซิร์ฟเวอร์เขียนได้ หรือโฟลเดอร์ย่อยปี/เดือนที่เพิ่งสร้างได้เจ้าของผิดคนมา การเขียนก็ล้มเหลว

ls -ld wp-content/uploads
ls -ld wp-content/uploads/2026/07

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

กิ่ง F — ชื่อไฟล์

เป็นการตรวจที่ถูกที่สุดในรายการนี้ ทำตั้งแต่แรกได้เลยแม้จะมีโอกาสน้อยที่สุด เปลี่ยนชื่อไฟล์เป็นตัวพิมพ์เล็ก ตัวเลข และขีดกลางล้วน ๆ ไม่มีเครื่องหมายเสริมสัทอักษร อะพอสทรอฟี แอมเปอร์แซนด์ # หรืออักขระที่ไม่ใช่ละติน แล้วอัพโหลดใหม่ อักขระพิเศษบางครั้งไปสะดุดกฎความปลอดภัย หรือพังบนระบบไฟล์ที่ตั้งค่าการเข้ารหัสไม่ตรงกัน ใช้เวลาสิบวินาทีเพื่อตัดออกจากรายการ

สิ่งที่ไม่ควรทำ

อย่าเริ่มด้วยการปิดปลั๊กอินทั้งหมด มันกระทบการใช้งาน และทดสอบได้แค่กิ่ง A กับกิ่ง D เท่านั้น คำตอบจากแท็บ network บอกคุณได้มากกว่าภายในห้าวินาที

อย่าใส่บรรทัด handler มั่ว ๆ ลงใน .htaccess สคริปต์ที่แชร์กันซึ่งเพิ่มคำสั่ง SetHandler หรือ AddHandler ตั้งอยู่บนสมมติฐานว่าโฮสต์ตั้งค่า PHP แบบหนึ่งเท่านั้น บนสแตกที่ไม่ตรงกัน มันทำให้เว็บทั้งเว็บล่มด้วย 500

อย่ารับว่า “ลองใหม่แล้วผ่าน” คือแก้แล้ว การสำเร็จแบบสุ่มคือลายเซ็นของกิ่ง B และมันจะกลับมาทันทีที่เซิร์ฟเวอร์งานหนัก หรือมีคนอัพโหลดไฟล์ที่ใหญ่กว่าเดิม

ยังติดอยู่ใช่ไหม

ถ้าคำตอบเป็น 200 สะอาด ๆ พร้อม JSON ที่ถูกต้อง แต่การอัพโหลดยังล้มเหลว แสดงว่าจุดที่พังอยู่หลังจากไฟล์ลงพื้นที่แล้ว ซึ่งมักเป็นปลั๊กอินที่เกี่ยวเข้ากับขั้นตอนประมวลผลไฟล์แนบแล้วโยน fatal error ออกมา หรือปลั๊กอินบีบอัดภาพที่ยิงคำขอของตัวเองไปยังบริการภายนอกแล้วหมดเวลา เปิด WP_DEBUG_LOG ทำให้เกิดปัญหาซ้ำ แล้วเอา fatal error ที่ได้ไปรันผ่าน ตัวถอดรหัส error log เพื่อดูว่าไฟล์ไหนและ hook ไหนที่รับผิดชอบจริง ๆ

FAQ

คำถาม

HTTP error ตอนอัพโหลดรูปเข้า WordPress หมายความว่าอะไร

แปลว่าตัวอัพโหลดในเบราว์เซอร์ส่งไฟล์ไปที่เซิร์ฟเวอร์แล้ว แต่ได้คำตอบกลับมาเป็นสิ่งที่มันตีความเป็นผลสำเร็จไม่ได้ ข้อความนี้บอกอาการ ไม่ได้บอกสาเหตุ ทั้งโปรเซส PHP ที่พัง ไฟร์วอลล์ที่บล็อก สถานะ 403 และการตอบกลับที่ว่างเปล่า ล้วนทำให้ขึ้นข้อความสามคำเดียวกันนี้

ทำไมรูปเดียวกันบางครั้งอัพโหลดผ่าน บางครั้งไม่ผ่าน

อาการที่เกิดบ้างไม่เกิดบ้างเกือบทั้งหมดชี้ไปที่หน่วยความจำหรือ CPU ไม่พอ มากกว่าจะเป็นลิมิตในการตั้งค่า การย่อภาพขนาดใหญ่ต้องใช้หน่วยความจำก้อนโตชั่วขณะ และบนโฮสต์แบบแชร์ ปริมาณที่ว่างจะเปลี่ยนไปตามภาระของเซิร์ฟเวอร์ ส่วนลิมิตตายตัวอย่าง post_max_size จะพังเหมือนเดิมทุกครั้งไม่มีพลาด

การสลับ WordPress จาก Imagick ไปใช้ GD แก้ HTTP error ได้ไหม

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

จะรู้ได้อย่างไรว่าไฟร์วอลล์ของโฮสต์กำลังบล็อกการอัพโหลด

เปิดเครื่องมือ network ในเบราว์เซอร์ อัพโหลดไฟล์ แล้วดูรหัสสถานะที่ได้กลับมาจาก async-upload.php ถ้าเป็น 403 หรือ 406 พร้อมเนื้อหาเป็น HTML แปลว่า web application firewall หรือกฎ mod_security ปฏิเสธคำขอนั้น แต่ถ้าเป็น 500 หรือได้คำตอบเปล่า ๆ ชี้ไปที่ PHP พังมากกว่า

เพิ่ม upload_max_filesize แล้วจะแก้ HTTP error ได้ไหม

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

ชื่อไฟล์ทำให้เกิด HTTP error ใน WordPress ได้ไหม

ได้ แม้จะเป็นกิ่งที่พบน้อยที่สุด อักขระที่มีเครื่องหมายเสริมสัทอักษร อะพอสทรอฟี แอมเปอร์แซนด์ และตัวอักษรที่ไม่ใช่ละติน อาจไปสะดุดกฎความปลอดภัยหรือทำให้พาธเพี้ยนบนระบบไฟล์ที่ตั้งค่าการเข้ารหัสไม่ตรงกัน การเปลี่ยนชื่อเป็นตัวพิมพ์เล็ก ตัวเลข และขีดกลาง ไม่มีต้นทุนอะไรเลย และตัดกิ่งนี้ทิ้งได้ในสิบวินาที