← كل المقالات

حل خطأ 413 Request Entity Too Large في Nginx وPHP

حل خطأ 413 عند رفع الملفات بتحديد الطبقة التي رفضت الطلب وضبط الحدود في Cloudflare وNginx وPHP والتطبيق ثم اختبار الحجم الفعلي.

يبني بكري عبدالسلام مواقع الويب والتطبيقات والتكاملات ومنتجات ووردبريس، ويوثق مركز بكري التقني القرارات التقنية وراء هذا العمل.

الخلاصة

الملف يمر عبر عدة طبقات، وأصغر حد بينها هو الذي يقرر النتيجة. حدد مصدر 413 ثم اضبط حداً واضحاً ومحدود النطاق في كل طبقة.

يعني الرد 413 Content Too Large أن جسم الطلب تجاوز الحد المسموح في إحدى الطبقات. قد يمر الملف عبر Cloudflare ثم Nginx ثم PHP-FPM وأخيراً قواعد التحقق داخل التطبيق. لذلك لا يكفي تعديل إعداد واحد إذا ظل حد أصغر أمامه.

حدد أولاً الحجم الذي يحتاجه المنتج فعلاً. رفع صورة بحجم 20MB لا يبرر فتح الموقع كله لطلبات بحجم عدة Gigabytes.

حدد الطبقة التي أعادت الاستجابة 413

نفذ طلباً تجريبياً مع عرض Headers، وراقب سجل Nginx في نفس اللحظة:

curl -i -F "file=@sample.bin" https://example.com/upload
sudo tail -f /var/log/nginx/error.log

عندما يرفض Nginx الطلب ستجد غالباً:

client intended to send too large body

إذا لم يصل الطلب إلى سجلات Nginx، فالرفض قد يكون من CDN أو Proxy سابق. لا تكشف Origin IP للعامة من أجل الاختبار. استخدم شبكة مصرحاً بها وHost Header الصحيح.

راجع أيضاً Status Code. قد يعيد Laravel أو WordPress الرد 422 بسبب Validation؛ هنا رفع حدود السيرفر لن يغير قاعدة التطبيق.

اضبط client_max_body_size في Nginx

يمكن وضع client_max_body_size داخل http أو server أو location. الأفضل أن يكون في أضيق نطاق يحتاج الرفع:

server {
    server_name example.com;

    location /upload {
        client_max_body_size 25m;
        try_files $uri $uri/ /index.php?$query_string;
    }
}

افحص الإعداد ثم أعد تحميل Nginx:

sudo nginx -t
sudo systemctl reload nginx

إذا لم تتغير النتيجة، اعرض الإعداد الذي حمّله Nginx فعلاً:

sudo nginx -T | grep -n client_max_body_size

قد تكون عدلت ملفاً غير مربوط داخل sites-enabled أو توجد قيمة أكثر تحديداً داخل Location أخرى.

طابق حدود PHP

راجع قيم FPM لا قيم PHP CLI فقط:

php --ini
php -i | grep -E 'upload_max_filesize|post_max_size|max_file_uploads'

قد يستخدم PHP-FPM ملف php.ini مختلفاً. استخدم أدوات الاستضافة أو php-fpm -i، وإن أنشأت صفحة phpinfo() مؤقتة فاحذفها فوراً لأنها تعرض معلومات حساسة.

مثال لسياسة ملف واحد حتى 25MB:

upload_max_filesize = 25M
post_max_size = 28M
max_file_uploads = 10

يجب أن تكون post_max_size أكبر لأن Multipart Body يحتوي بيانات إضافية بجانب الملف. ثم أعد تشغيل FPM:

sudo systemctl restart php8.3-fpm

لا ترفع memory_limit تلقائياً إلى حجم الملف. PHP يخزن الرفع مؤقتاً، لكن معالجة صورة كاملة أو قراءتها داخل الذاكرة قد تستهلك أضعاف الحجم. قس الاستهلاك الحقيقي.

راجع حد Cloudflare

إذا كان الـDNS يعمل عبر Cloudflare Proxy، فالطلب يجب أن يمر أولاً من حد الخطة. بحسب توثيق Cloudflare في يوليو 2026: الحد 100MB لخطة Free وPro، و200MB لـBusiness، و500MB افتراضياً لـEnterprise. راجع دائماً الحدود الحالية للطلبات لأن القيم قد تتغير.

عندما تحتاج ملفات أكبر من حد الـEdge استخدم بنية مختلفة:

  • رفع مباشر إلى Object Storage عبر Signed URL قصير العمر.
  • Multipart أو Resumable Upload.
  • Host رفع منفصل ومحمي مع Firewall وRate Limit.
  • فحص الحجم في المتصفح قبل بدء النقل.

لا توقف Cloudflare عن الموقع كله بسبب Endpoint واحدة.

اجعل قواعد الرفع داخل التطبيق واضحة

حد Nginx هو سقف للنقل وليس سياسة المنتج. يجب على التطبيق التحقق من:

  • صلاحية المستخدم لتنفيذ الرفع.
  • الحجم وفق نوع الحساب.
  • نوع الملف ومحتواه الفعلي.
  • اسم تخزين يولده السيرفر.
  • عدم وضع ملفات غير موثوقة في مسار قابل للتنفيذ.

انتبه لاختلاف الوحدات بين Nginx وPHP وقواعد Framework. اختبر الحد الفعلي ولا تعتمد على تشابه الأرقام في الملفات.

اختبر أسفل الحد وأعلاه

أنشئ ملفات اختبار بلا بيانات حساسة:

truncate -s 24M below-limit.bin
truncate -s 26M above-limit.bin

curl -o /dev/null -sS -w '%{http_code}\n' \
  -F "file=@below-limit.bin" https://example.com/upload

curl -o /dev/null -sS -w '%{http_code}\n' \
  -F "file=@above-limit.bin" https://example.com/upload

الاختبار الجيد يثبت أن الملف أسفل الحد ينجح، والملف أعلاه يحصل على رسالة واضحة، ولا تمتلئ مساحة Temporary Storage مع عدة عمليات متزامنة، ولا تبقى أجزاء يتيمة بعد الفشل.

أخطاء شائعة

تتكرر المشكلة عند تعديل php.ini الخاص بالـCLI، أو وضع Directive في Server Block غير مستخدم، أو جعل post_max_size أصغر، أو نسيان Reload، أو تجاهل Cloudflare.

وثق الحد بجانب ميزة الرفع وأضف اختبار Boundary للإصدار. للمشاكل الأخرى بين Nginx وPHP-FPM راجع دليل حل 502 وقائمة Nginx للإنتاج.

أسئلة شائعة

لماذا تصبح بيانات الرفع فارغة في PHP؟

عندما يتجاوز Body كاملة قيمة post_max_size قد ترفض PHP الطلب قبل معالجة الملفات، فتظهر البيانات المتوقعة فارغة. افحص إعداد FPM والحجم الفعلي معاً.

هل تعديل Nginx يتجاوز حد Cloudflare؟

لا. إذا رفضت Cloudflare الطلب فلن يصل إلى Nginx. استخدم حداً تدعمه الخطة أو Signed Upload مباشرة إلى Storage.

مراجع رسمية

لديك سؤال عن هذا الدليل أو فكرة لتعاون تقني؟ تواصل مع بكري عبر المركز التقني.

نهاية الملاحظة.