Apache و Nginx
رفع خطای 413 Request Entity Too Large در Nginx
خطای 413 Request Entity Too Large یعنی Nginx حجم درخواست یا فایل آپلودی را از سقف مجاز بزرگ تر دیده و قبل از رسیدن به PHP رد کرده است. راه رفع آن بالا بردن client_max_body_size در Nginx و هماهنگ کردن upload_max_filesize و post_max_size در PHP است.
خطای 413 Request Entity Too Large معمولا هنگام آپلود عکس، افزونه یا فایل پشتیبان در وردپرس دیده می شود. Nginx حجم بدنه درخواست را با سقف client_max_body_size مقایسه می کند و اگر بزرگ تر باشد، همان جا خطای 413 برمی گرداند و درخواست هرگز به PHP نمی رسد. برای رفع خطای 413 Request Entity Too Large این دستور را به سرور یا سایت اضافه کنید، کانفیگ را با nginx -t تست کنید و Nginx را reload کنید. بعد از آن باید دو سقف PHP هم بالا بیایند، وگرنه آپلود در لایه بعدی رد می شود.
این خطا از کجا می آید
مقدار پیش فرض client_max_body_size در Nginx یک مگابایت است. یعنی هر آپلودی که از 1MB بزرگ تر باشد، تا وقتی این دستور را تغییر نداده اید، با 413 رد می شود. مستندات رسمی آن در ngx_http_core_module آمده و اگر مقدار را 0 بگذارید، بررسی حجم کلا خاموش می شود.
برای تایید این که خطا واقعا از Nginx است، error.log را نگاه کنید:
sudo tail -n 20 /var/log/nginx/error.log | grep "too large body"
خروجی شبیه این است:
client intended to send too large body: 8388608 bytes, client: 203.0.113.5, server: example.com, request: "POST /wp-admin/async-upload.php HTTP/1.1", host: "example.com"
عدد داخل خط، حجم فایلی است که فرستاده شده. اگر چنین خطی نمی بینید، یا خطا از لایه دیگری مثل CDN و فایروال می آید، یا هنوز به Nginx نرسیده اید.
تنظیم client_max_body_size در Nginx
این دستور در سه جا معتبر است: بلوک http برای کل سرور، بلوک server برای یک سایت و بلوک location برای یک آدرس خاص. بهتر است سقف را فقط برای سایتی که لازم دارد و تا حد معقول بالا ببرید. فایل سایت معمولا در /etc/nginx/sites-available/ است:
server {
server_name example.com;
client_max_body_size 64M;
# بقیه تنظیمات سایت
}
اگر فقط آدرس آپلود نیاز دارد، می توانید دستور را داخل همان location بگذارید و بقیه سایت با سقف کم بماند:
location = /wp-admin/async-upload.php {
client_max_body_size 128M;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
پیش از ویرایش از فایل کانفیگ نسخه پشتیبان بگیرید و بعد از تغییر، sudo nginx -t را اجرا کنید. فقط اگر syntax is ok دیدید، sudo systemctl reload nginx را بزنید. restart لازم نیست و reload اتصال های جاری را قطع نمی کند.
اگر چند فایل در /etc/nginx/conf.d/ یا sites-enabled وجود دارد، با sudo nginx -T | grep client_max_body_size ببینید دستور در کجاها تعریف شده. مقداری که در بلوک پایین تر (location) نوشته شود، مقدار بالاتر را برای همان آدرس عوض می کند.
تنظیم PHP برای آپلود فایل بزرگ
درست کردن Nginx تنها کافی نیست. PHP برای حجم آپلود دو سقف جداگانه دارد و هر دو باید به اندازه کافی بالا باشند:
| تنظیم PHP | کاربرد | نکته |
|---|---|---|
upload_max_filesize | سقف حجم هر فایل آپلودی | باید از بزرگ ترین فایل مورد انتظار کمتر نباشد |
post_max_size | سقف کل بدنه درخواست POST | باید از upload_max_filesize بیشتر یا مساوی باشد |
memory_limit | حافظه مجاز هر اسکریپت | برای پردازش تصویر و بکاپ باید به اندازه کافی باشد |
max_execution_time | مدت اجرای اسکریپت | آپلود کند را ممکن است نیمه کاره رها کند |
ترتیب منطقی این است: client_max_body_size در Nginx بزرگ تر از post_max_size و آن هم بزرگ تر یا مساوی upload_max_filesize باشد. اگر این ترتیب رعایت نشود، یکی از لایه ها فایل را بدون پیام روشن رد می کند. اگر post_max_size کوچک باشد، PHP بدنه را خالی می خواند و در وردپرس یا فرم هایتان داده ای دریافت نمی شود.
روی VPS با PHP-FPM این مقدارها را در php.ini مربوط به FPM تغییر دهید. در Ubuntu معمولا همین فایل است:
/etc/php/8.2/fpm/php.ini
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
بعد از تغییر، سرویس را reload کنید، مثلا sudo systemctl reload php8.2-fpm. نام سرویس و مسیر php.ini با نسخه PHP و توزیع فرق می کند. با php-fpm8.2 -i | grep php.ini یا از طریق صفحه phpinfo() می توانید فایل واقعی را پیدا کنید. اگر روی همان سرور برای سایت ها فایل .user.ini یا pool جدا دارید، ممکن است مقدار آن ها از php.ini بالاتر حکم کند.
اگر وردپرس دارید
در وردپرس بعد از اصلاح سقف ها، از بخش رسانه، گزینه افزودن، حداکثر حجم فایل مجاز را بخوانید. آن عدد همان مقداری است که از PHP می آید و باید با آنچه تنظیم کرده اید یکی باشد. اگر مقدار قدیمی را نشان داد، یا PHP reload نشده یا سایت از یک pool دیگر سرویس می گیرد.
در شبکه چندسایتی (Multisite) علاوه بر این ها یک سقف جدا در مدیریت شبکه، بخش تنظیمات شبکه و قسمت Upload Settings وجود دارد. مقدار آن به کیلوبایت است و می تواند از سقف PHP پایین تر باشد. افزونه های بکاپ هم گاهی فایل را تکه تکه می فرستند، پس اگر فقط بکاپ بزرگ خطا می دهد، تنظیم همان افزونه را نگاه کنید و حجم تکه را کوچک تر کنید.
اگر آپلود طولانی با 504 تمام می شود نه 413، مشکل در مدت زمان است و راهنمای خطای 504 Gateway Timeout در Nginx را بخوانید.
تنظیم یک بار برای چند سایت
اگر روی یک سرور چند سایت دارید، دستور را در هر فایل تکرار نکنید. یک فایل کوچک در /etc/nginx/snippets/ بسازید و آن را در server block هر سایتی که لازم دارد include کنید:
# /etc/nginx/snippets/upload-limit.conf
client_max_body_size 64M;
server {
server_name example.com;
include snippets/upload-limit.conf;
}
این طور برای تغییر سقف فقط یک فایل را ویرایش می کنید. دقت کنید که اگر همان دستور را مستقیم در server block هم نوشته باشید، Nginx به خاطر تعریف دوباره در همان سطح خطا می دهد و nginx -t آن را نشان می دهد.
فایل های خیلی بزرگ را از مسیر دیگری منتقل کنید
آپلود چند صد مگابایتی از مرورگر ذاتا شکننده است و با قطع شدن اینترنت از اول شروع می شود. برای بکاپ، دامپ دیتابیس و فایل های حجیم رسانه، بهتر است از SFTP یا scp استفاده کنید. در وردپرس هم دستور wp media import در WP-CLI فایل ها را مستقیم از سرور وارد کتابخانه رسانه می کند و از مسیر آپلود وب رد نمی شود. دامپ دیتابیس را هم با خود MySQL وارد کنید و از phpMyAdmin که به همین سقف ها وابسته است استفاده نکنید.
یک نکته هم درباره دیسک وجود دارد. Nginx بدنه های بزرگ را قبل از دادن به PHP در یک پوشه موقت می نویسد (مسیر آن با client_body_temp_path تعیین می شود). اگر پارتیشن سرور پر باشد، آپلود بزرگ به جای 413 با خطای 500 تمام می شود و در error.log عبارت مربوط به نوشتن فایل موقت دیده می شود.
وقتی 413 از جای دیگری می آید
بعد از بالا بردن همه سقف ها اگر هنوز 413 می بینید، بررسی کنید پیش از Nginx چه لایه ای وجود دارد. Cloudflare و بقیه CDN ها بسته به پلن، سقف حجم درخواست دارند و آن را در مستندات خودشان نوشته اند. اگر خطا در صفحه ای با برند Cloudflare نمایش داده می شود، مشکل از سقف Nginx نیست. همان آپلود را با آدرس مستقیم سرور یا از طریق فایل hosts امتحان کنید تا مطمئن شوید.
اگر Nginx جلوی Apache یا یک بک اند دیگر است، آن سرویس هم سقف خودش را دارد (مثلا LimitRequestBody در Apache). در پنل Plesk با Nginx جلوی Apache، تنظیمات Nginx از Domains، Apache & nginx Settings و قسمت Additional nginx directives قابل تغییر است. جزئیات سقف PHP در Plesk در آموزش تنظیمات PHP و حجم آپلود در Plesk آمده است.
ترتیب پیشنهادی برای بررسی
وقتی مطمئن نیستید خطا از کدام لایه می آید، این ترتیب کمترین رفت و برگشت را دارد:
- خطا را از مرورگر یا با curl تکرار کنید و کد پاسخ را ببینید. کد 413 از Nginx یا CDN می آید و آپلودی که بی صدا رد می شود معمولا از PHP است.
- error.log را برای عبارت
too large bodyجست وجو کنید. client_max_body_sizeرا در سطحhttp،serverوlocationباnginx -Tپیدا کنید و ببینید کدام یک اعمال می شود.- مقدارهای PHP را با
phpinfo()یاphp -iبرای FPM بخوانید و با Nginx مقایسه کنید. - بعد از هر تغییر، سرویس مربوط را reload کنید و آپلود را دوباره امتحان کنید.
هاست اشتراکی cPanel
اگر هاست اشتراکی دارید، به nginx.conf دسترسی ندارید و لازم هم نیست. در cPanel از بخش MultiPHP INI Editor مقدارهای upload_max_filesize و post_max_size را تغییر دهید. سقف مجاز هر پلن ممکن است محدود باشد و اگر عدد بالاتر ذخیره نشد، باید از پشتیبانی بپرسید. روش کار با نسخه PHP و memory_limit در راهنمای نسخه PHP و memory_limit در cPanel توضیح داده شده است.
چطور بفهمیم مشکل حل شده است
یک فایل تستی با حجم بیش از سقف قبلی ولی کمتر از سقف جدید بسازید و آن را از مسیر معمول آپلود کنید. روی لینوکس برای ساخت فایل 20 مگابایتی این دستور کافی است:
dd if=/dev/zero of=test-20mb.bin bs=1M count=20
اگر آپلود تمام شد و در error.log دیگر client intended to send too large body ثبت نشد، Nginx درست است. اگر آپلود تمام شد ولی فایل در وردپرس ظاهر نشد، لاگ PHP-FPM و فضای دیسک را بررسی کنید. فایل های موقت آپلود در پوشه /tmp می نشینند و پر بودن دیسک یا inode هم همین علامت را می دهد.
سقف را بیشتر از نیاز واقعی بالا نبرید. هر آپلود بزرگ، یک worker PHP را برای مدتی درگیر می کند و بدنه های خیلی حجیم می توانند دیسک و پهنای باند سرور را اشغال کنند. اگر پنل های مدیریتی شما فقط برای کاربران مطمئن فایل می گیرند، سقف بالاتر را فقط روی همان مسیر بگذارید. برای ادامه تنظیم سرور وردپرس، کانفیگ Nginx برای وردپرس و رفع 404 پیوندهای یکتا را هم ببینید.