رفعٌ يفشل عند حدٍّ حجميّ هو حدّ — انظر الخطأ 413. أمّا رفعٌ يفشل في منتصفه عند حجم غير ثابت، والاتصال يسقط ببساطة، فهو مهلة في مكان ما على الطريق.

المهل التي تُرفَع، جميعها

# nginx
client_body_timeout 300s;
client_max_body_size 512M;
send_timeout 300s;
fastcgi_read_timeout 300s;
proxy_read_timeout 300s;
; php
max_execution_time = 300
max_input_time = 300      ; the one that is forgotten - it covers the UPLOAD itself

قيمة max_input_time تحدّ الزمن الذي يقضيه PHP في استقبال الطلب. وهي منفصلة عن max_execution_time، وقيمتها الافتراضية منخفضة، وهي ما يقتل رفعًا بطيئًا من هاتف.

القرص والمساحة المؤقّتة

df -h /tmp /var/lib/php/tmp
grep upload_tmp_dir /etc/php/8.3/fpm/php.ini

الرفع يُكتَب في ملفّ مؤقّت أوّلًا. فإن امتلأ نظام الملفّات ذاك، فشلت الكتابة في منتصف النقل وسقط الاتصال بلا رسالة في أي مكان.

وابحث عمّا سُجّل

sudo tail -50 /var/log/nginx/error.log
sudo journalctl -u php8.3-fpm -n 50 --no-pager

عبارة client intended to send too large body هي حدّ الحجم. وعبارتا timed out وupstream prematurely closed هما المهل المذكورة أعلاه. وغياب أي شيء يعني غالبًا أن المتصفّح أو وسيطًا استسلم قبل الخادم.

خلف Cloudflare للوسيط سقف رفعٍ خاصّ به في الخطط الأدنى، وهو يُطبَّق مهما ضبطت محليًّا. ارفع إلى نطاق فرعيّ يتجاوز الوسيط، أو ارفع على أجزاء.

والحلّ الصحيح للملفّات الكبيرة

الرفع المجزّأ أو القابل للاستئناف يرسل الملفّ الكبير طلباتٍ صغيرة كثيرة، فلا يطول أي طلب منفرد، والاتصال الساقط يُستأنف بدل أن يبدأ من جديد. ولأي شيء فوق بضع مئات من الميغابايت هو الجواب الموثوق الوحيد.