یکی از آن پرونده‌هایی که در ذهنم ماند، مربوط به مشتری‌ای بود که برای یک فروشگاه ساز موسیقی، فایل صوتی نمونه‌کارها را آپلود می‌کرد و مدام پیام می‌گرفت: «فایل با موفقیت آپلود نشد». اول فکر کردیم فایل خراب است؛ بعد گفتیم حجمش زیاد است؛ بعد کسی پیشنهاد داد افزونهٔ فرم‌ساز را عوض کنیم. سه روز گذشت و هر بار مشکل در قالب دیگری برگشت. وقتی نشستم پشت سرور و لاگ‌ها را باز کردم، در پنج دقیقه مشخص شد مسئله در یک سطح بسیار ساده‌تر بود: upload_max_filesize روی سرور روی مقدار پیش‌فرض ۲ مگابایت مانده بود و هیچ‌کس به آن نگاه نکرده بود. تجربه‌ام این است که خطاهای آپلود در وردپرس، همان خطاهایی هستند که بیشترین وقت را با کمترین نتیجه هدر می‌دهند — چون شبیه هم به نظر می‌رسند، ولی هر کدام یک ریشهٔ متفاوت دارند.

در این مقاله، همان مسیر تشخیصی را که در پروژه‌های واقعی برای رفع خطاهای آپلود فایل در وردپرس طی می‌کنم، گام‌به‌گام باز می‌کنم. اگر با ساختار کلی وردپرس آشنا نیستید، پیشنهاد می‌کنم ابتدا وردپرس چیست و چگونه شروع کنیم را بخوانید؛ چون فهم خطاهای آپلود، بدون درک لایهٔ PHP و تنظیمات سرور تقریباً غیرممکن است.

خطای آپلود فایل در وردپرس چیست؟

وردپرس برای مدیریت فایل‌ها (تصویر، PDF، ویدئو، فایل صوتی و…) از یک مسیر مشخص استفاده می‌کند: کاربر فایل را انتخاب می‌کند، مرورگر آن را به‌صورت یک درخواست HTTP از نوع multipart/form-data به سرور می‌فرستد، PHP فایل را در پوشهٔ موقت روی سرور ذخیره می‌کند، وردپرس آن را اعتبارسنجی می‌کند و اگر همه‌چیز درست باشد، به پوشهٔ wp-content/uploads منتقل می‌کند. این مسیر در ظاهر ساده است، اما چند ایستگاه دارد و در هر ایستگاه، احتمال شکست وجود دارد.

خطای آپلود در وردپرس، دقیقاً زمانی رخ می‌دهد که یکی از این ایستگاه‌ها از پذیرش فایل خودداری کند: یا PHP فایل را از همان ابتدا رد کرده (به‌خاطر حجم یا MIME)، یا نتوانسته به پوشهٔ uploads دسترسی داشته باشد، یا وردپرس بعد از دریافت، آن را معتبر ندانسته. همین چند‌لایه‌بودن مسیر، دلیل آن است که یک خطای آپلود، می‌تواند از یک محدودیت سادهٔ ۲ مگابایتی PHP تا یک سیاست امنیتی پیچیده باشد.

از منظر کاربر، این خطا همیشه یک شکل ندارد. گاهی پیام «The uploaded file exceeds the upload_max_filesize directive in php.ini» می‌بینید؛ گاهی فقط «خطا در آپلود فایل» بدون هیچ توضیح؛ و گاهی هم به‌طور مرموز، فایل آپلود می‌شود اما به کتابخانهٔ رسانه نمی‌رسد. هر کدام از این پیام‌ها، یک سرنخ متفاوت است.

خطای آپلود، پیام «این فایل بد است» نیست؛ بیشتر وقت‌ها پیام «یک جایی از مسیر، باز نیست» است. تا وقتی این مسیر را ایستگاه‌به‌ایستگاه نبینیم، حدس‌زدن فقط وقت می‌گیرد.

انواع خطاهای آپلود که ممکن است ببینید

در پروژه‌هایی که با این خطاها درگیر بوده‌ام، پنج پیام یا حالت رایج تکرار شده‌اند. تشخیص نوع، نیمی از حل است:

پیام یا حالتکجا ظاهر می‌شودریشهٔ محتمل
The uploaded file exceeds the upload_max_filesize directive in php.iniکتابخانهٔ رسانه، آپلود مستقیممحدودیت حجم PHP
The uploaded file exceeds the MAX_FILE_SIZE directiveفرم‌های سفارشیمحدودیت فرم سمت HTML
The uploaded file could not be moved to wp-content/uploadsکتابخانهٔ رسانهمجوز پوشهٔ uploads
This file type is not allowedپیام خشک در ویرایشگرMIME Type مجاز نیست
آپلود بدون پیام، فایل ناپدید می‌شودکتابخانهٔ رسانه یا فرمحافظه، Timeout، یا افزونهٔ امنیتی

نوع دوم و آخر، سخت‌ترین‌ها هستند — چون یا پیام دقیق نمی‌دهند یا آن‌قدر عمومی هستند که نمی‌دانید از کجا شروع کنید. اگر با نوع آخر روبه‌رو هستید، به بخش «روش گام‌به‌گام تشخیص» بروید.

چرا وردپرس آپلود را رد می‌کند؟

وردپرس به‌عنوان یک سیستم مدیریت محتوا، فایل‌های کاربران را با اعتماد کامل نمی‌پذیرد و این سیاست، درست است. هر فایل آپلودی، یک ریسک امنیتی بالقوه است؛ از یک فایل PHP که می‌تواند در پوشهٔ uploads اجرا شود تا یک تصویر ویروسی با کد درونش. به همین دلیل، وردپرس چند لایه محافظت دارد:

  1. لایهٔ اول، محدودیت‌های PHP است که از همان ابتدا حجم و تعداد فایل را در سطح سرور کنترل می‌کند.
  2. لایهٔ دوم، اعتبارسنجی MIME Type وردپرس است که فرمت فایل را با لیست مجاز مقایسه می‌کند.
  3. لایهٔ سوم، سیاست‌های خود کاربر است — یعنی افزونه‌های امنیتی که می‌توانند فراتر از وردپرس، فایل‌ها را محدود کنند.

درک این لایه‌ها، کلید تشخیص است. اگر خطای شما از لایهٔ اول می‌آید، باید تنظیمات سرور را تغییر دهید. اگر از لایهٔ دوم، باید فرمت فایل یا allowlist را بررسی کنید. اگر از لایهٔ سوم، باید افزونهٔ امنیتی را بررسی یا تنظیم کنید. سه مسیر مختلف، سه نتیجهٔ مختلف.

ریشهٔ اول: محدودیت حجم فایل

شایع‌ترین ریشه، همانی است که در ابتدای مقاله به آن اشاره کردم: محدودیت حجم فایل در سطح PHP. PHP دو پارامتر کلیدی دارد که در مسیر آپلود اثر می‌گذارند:

  • upload_max_filesize: حداکثر حجم یک فایل تنها. مقدار پیش‌فرض رایج، 2M است.
  • post_max_size: حداکثر حجم کل درخواست POST که معمولاً باید بزرگ‌تر از upload_max_filesize باشد.

نکتهٔ ظریف: اگر post_max_size از upload_max_filesize کوچک‌تر باشد، حتی فایل کوچکی که از محدودیت اول عبور کرده باشد، در ارسال به سرور رد می‌شود. در تجربه‌ام، این ترکیب اشتباه، دلیل بسیاری از خطاهای «مرموز» است.

از منظر تجربهٔ میدانی، این محدودیت معمولاً یک ریشهٔ دوم هم دارد: هاست‌های اشتراکی به‌دلیل اشتراک منابع، این مقادیر را عمداً پایین نگه می‌دارند. اگر سایت شما روی هاست ارزان و اشتراکی است و از همان ابتدا این خطا را می‌گیرید، شاید راه‌حل واقعی، افزایش این مقادیر نیست؛ در نظر گرفتن یک هاست مناسب‌تر است. این تصمیم را در هاست چیست و چگونه انتخاب کنیم با معیارهای عددی باز کرده‌ام.

ریشهٔ دوم: محدودیت حافظهٔ PHP

گاهی فایل حجم کمی دارد و از تمام محدودیت‌های حجمی عبور می‌کند، اما در لحظهٔ پردازش (مثلاً تغییر سایز تصویر یا استخراج متادیتا) با کمبود حافظه مواجه می‌شود و PHP خطا می‌دهد. در این حالت، کاربر معمولاً خطای «Internal Server Error» یا «Allowed memory size exhausted» می‌بیند، نه خطای مستقیم آپلود. اما این خطا، بخشی از مسیر آپلود است و اگر آن را به‌عنوان خطای حافظه ببینید، مسیر تشخیص جداگانه‌ای دارد.

برای ریشه‌ای‌کردن این مسئله، خطای Memory Limit در وردپرس را جداگانه در مقاله‌ای بررسی کرده‌ام؛ چون تشخیص آن، حتی اگر در مسیر آپلود رخ دهد، منطق متفاوتی دارد. نکتهٔ کاربردی: اگر فقط در آپلود فایل‌های سنگین خطای حافظه می‌گیرید، احتمالاً باید هم memory_limit را افزایش دهید و هم در صورت امکان، پردازش تصویر را به‌صورت batch انجام دهید.

ریشهٔ سوم: مجوز پوشهٔ uploads

پوشهٔ wp-content/uploads جایی است که فایل‌های آپلودی وردپرس ذخیره می‌شوند. اگر مجوز این پوشه اشتباه باشد — چه برای کاربر مالک، چه برای گروه، چه برای کاربر وب‌سرور — PHP نمی‌تواند فایل را در آن بنویسد و پیام «The uploaded file could not be moved to wp-content/uploads» می‌دهد. این خطا در ظاهر شبیه به خطای Permission عمومی است، اما مسیر رفع آن متفاوت است.

در پروژه‌های خودم، بیشتر وقت‌ها دیده‌ام که پوشهٔ uploads، مجوز 755 ندارد یا زیرپوشه‌های سال/ماه با کاربر اشتباهی ثبت شده‌اند. گاهی هم به‌خاطر انتقال سایت بین هاست‌ها، مالکیت فایل‌ها جابه‌جا شده و وب‌سرور نمی‌تواند بنویسد. این ریشه، آن‌قدر با خطاهای Permission درهم‌تنیده است که در رفع خطای Permission در وردپرس به‌طور جداگانه و مفصل بازش کرده‌ام. اگر می‌خواهید با مدل مجوز و مالکیت در لینوکس آشنا شوید، آن مقاله نقطهٔ شروع دقیقی است.

ریشهٔ چهارم: نوع فایل غیرمجاز (MIME Type)

وردپرس به‌طور پیش‌فرض فقط فرمت‌های مشخصی را برای آپلود می‌پذیرد: تصاویر (jpg, jpeg, png, gif, webp)، PDF، برخی فایل‌های متنی، و چند فرمت دیگر. اگر بخواهید فرمت دیگری — مثلاً .svg، .zip، .rar، یا یک فرمت اختصاصی — آپلود کنید، وردپرس با پیام «This file type is not allowed» رد می‌کند.

نکتهٔ ظریف: برای فایل‌های SVG که در طراحی سایت‌ها محبوب شده‌اند، وردپرس در حالت پیش‌فرض اجازه نمی‌دهد. این سیاست، درست است، چون SVG یک فایل XML است که می‌تواند شامل جاوااسکریپت مخرب باشد. اگر حتماً به SVG نیاز دارید، راه‌حل امن‌تر استفاده از افزونه‌هایی است که SVG را با اعتبارسنجی سخت‌گیرانه فعال می‌کنند. در این حالت، نکته‌هایی که در بهترین افزونه‌های امنیتی وردپرس مطرح شده‌اند، مستقیماً به‌کار می‌آید.

برای مجاز کردن فرمت‌های اضافی، وردپرس فیلتر upload_mimes را فراهم می‌کند. در بخش «مجاز کردن فرمت‌های خاص» این مقاله، نمونهٔ کد آن را می‌بینید.

ریشهٔ پنجم: مشکل پردازش تصویر (GD/Imagick)

وقتی شما یک تصویر آپلود می‌کنید، وردپرس تلاش می‌کند نسخه‌های مختلفی از آن را بسازد: تامبنیل، medium، large و… . این پردازش با کتابخانه‌های GD یا Imagick انجام می‌شود که باید روی سرور فعال باشند. اگر یکی از این کتابخانه‌ها نصب نباشد یا از فرمت‌های جدید (مثلاً WebP یا AVIF) پشتیبانی نکند، آپلود می‌تواند به‌ظاهر موفق شود ولی در مرحلهٔ ساخت سایزهای مختلف شکست بخورد.

نشانهٔ این ریشه، این است: فایل اصلی در کتابخانهٔ رسانه دیده می‌شود اما هیچ تامبنیل یا سایز دیگری ندارد؛ یا فایل اصلاً وارد کتابخانه نمی‌شود، ولی در پوشهٔ uploads (از طریق FTP) وجود دارد. تشخیص:

  1. یک فایل phpinfo.php موقت در ریشهٔ سایت بسازید که فقط شامل <?php phpinfo(); ?> باشد.
  2. در خروجی، بخش GD یا Imagick را ببینید.
  3. اگر GD فعال است، فرمت‌های پشتیبانی‌شده را چک کنید (مثلاً WebP از GD نسخهٔ ۲.۳ به بعد پشتیبانی می‌شود).
  4. بلافاصله پس از بررسی، فایل را پاک کنید.

اگر GD فعال نیست، از پشتیبانی هاست بخواهید آن را نصب کند. اگر فقط برای فرمت خاصی مثل WebP مشکل دارید، تصمیم بین نصب مجدد GD و استفاده از افزونهٔ تبدیل تصویر (که به‌جای پردازش در PHP، از سرویس بیرونی استفاده می‌کند) است.

ریشهٔ ششم: پرشدن فضای دیسک

گاهی هیچ محدودیت منطقی‌ای وجود ندارد — سرور شما به‌سادگی پر شده است. این وضعیت بیشتر در هاست‌های اشتراکی با فضای محدود (مثلاً ۵ یا ۱۰ گیگابایت) رخ می‌دهد. اگر فایل‌های آپلودشده قبلی، بکاپ‌های خودکار، لاگ‌های سنگین یا فایل‌های موقت، فضای دیسک را پر کرده باشند، PHP نمی‌تواند فایل جدید بنویسد.

تشخیص ساده است: در cPanel یا DirectAdmin، بخش «Disk Usage» یا «File Usage» را ببینید. اگر در مرز ظرفیت هستید، مقصر پیدا شده. راه‌حل: پاک‌سازی فایل‌های غیرضروری. سه دسته که در تجربه‌ام بیشترین فضا را اشغال می‌کنند:

  • بکاپ‌های قدیمی که در پوشهٔ هاست مانده‌اند.
  • تصاویر بدون استفاده که هنوز در کتابخانهٔ رسانه هستند.
  • لاگ‌های سنگین مثل debug.log یا لاگ‌های Apache.

قاعدهٔ تجربی من: هرگز بالای هشتاد درصد ظرفیت دیسک نروید. اگر نزدیک آن هستید، برنامهٔ پاک‌سازی یا ارتقای پلن هاست را جدی بگیرید. اطلاعات بیشتر در راهنمای انتخاب هاست آمده است.

ریشهٔ هفتم: افزونهٔ امنیتی سخت‌گیر

در برخی سایت‌ها، هیچ‌کدام از ریشه‌های بالا نیست؛ در عوض، یک افزونهٔ امنیتی یا یک قوانین خاص در .htaccess، آپلود را به‌صورت کلی محدود کرده است. نشانهٔ این سناریو: آپلود در یک صفحه کار می‌کند و در صفحهٔ دیگر نه؛ یا آپلود یک کاربر کار می‌کند و آپلود کاربر دیگر نه. این رفتار متناقض، نشانهٔ یک سیاست پویا است نه یک محدودیت ثابت.

تشخیص: افزونه‌های امنیتی را یک‌یکی غیرفعال کنید و بعد از هر بار، تست آپلود بگیرید. اگر بعد از غیرفعال کردن یک افزونه، آپلود کار کرد، مقصر پیدا شده. بعضی افزونه‌های امنیتی، لیست فرمت‌های مجاز را دقیق‌تر از وردپرس اعمال می‌کنند و همین می‌تواند شکست بیاورد. اگر رویکرد امنیتی افزونه‌تان را قبول دارید، می‌توانید فرمت لازم را در تنظیمات آن اضافه کنید؛ در غیر این صورت، فهرست بهترین افزونه‌های امنیتی وردپرس جایگزین‌های متعادل‌تری را نشان می‌دهد.

ریشهٔ هشتم: Timeout در آپلودهای سنگین

وقتی فایل‌های حجیم (چندصد مگابایت) آپلود می‌کنید، ممکن است فایل از تمام محدودیت‌های حجمی عبور کند اما در میانهٔ آپلود، Timeout بخورد. علتش معمولاً پارامتر max_execution_time در PHP است که پیش‌فرض ۳۰ تا ۶۰ ثانیه است. برای فایل‌های سنگین، این زمان کافی نیست.

دو راه‌حل دارید. اول، افزایش max_execution_time (در php.ini، .user.ini یا پنل هاست). دوم، استفاده از روش‌های جایگزین مثل آپلود از طریق FTP یا استفاده از افزونه‌های chunked upload که فایل را به قطعات کوچک تقسیم می‌کنند. راه‌حل دوم معمولاً حرفه‌ای‌تر است، چون بارِ حافظه و زمان را روی سرور پخش می‌کند. در بخش «آپلود فایل‌های سنگین» بیشتر بازش می‌کنم.

هرگاه آپلوd در یک ثانیهٔ مشخص شکست می‌خورد، آن ثانیه احتمالاً همان لحظه‌ای است که سقف max_execution_time به پایان رسیده؛ پس اول زمان را چک کنید، بعد حجم را.

روش گام‌به‌گام تشخیص

ترتیب زیر را در پروژه‌های خودم دنبال می‌کنم؛ از سریع‌ترین به دقیق‌ترین:

  1. پیام دقیق را بخوانید. اگر نام پارامتر PHP در پیام آمده (مثل upload_max_filesize)، مقصر همان است.
  2. حجم فایل را چک کنید. اگر فایل بزرگ‌تر از ۲ مگابایت است، مشکل احتمالاً همان محدودیت پیش‌فرض است.
  3. مقدار فعلی پارامترها را ببینید. با یک فایل موقت phpinfo.php، مقادیر upload_max_filesize، post_max_size، memory_limit و max_execution_time را ببینید.
  4. از طریق FTP فایل را آپلود کنید. اگر آپلود از FTP هم شکست خورد، مسئله در سرور است؛ اگر موفق بود، مسئله در PHP است.
  5. پوشهٔ uploads را چک کنید. مجوز 755 و مالکیت درست.
  6. افزونه‌های امنیتی را موقتاً غیرفعال کنید. اگر آپلود کار کرد، یک افزونه سیاست‌گذار مقصر است.
  7. لاگ خطای PHP را ببینید. با فعال‌سازی WP_DEBUG، خطاهای دقیق‌تری به دست می‌آورید.

برای فعال‌سازی لاگ، در wp-config.php پیش از خط /* That's all, stop editing! */ اضافه کنید:

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

لاگ در wp-content/debug.log ذخیره می‌شود. این روش، در پرونده‌های پیچیده که همهٔ حدس‌ها بی‌نتیجه ماندند، سرنخ نهایی را می‌دهد. اگر خطای آپلود باعث کندی سایت هم شده، پیشنهاد می‌کنم چرا بعضی قالب‌ها سایت را کند می‌کنند را هم ببینید؛ چون در بعضی سناریوها، آپلود فایل باعث می‌شود یک قالب سنگین، سایت را به‌طور کلی کندتر کند.

افزایش اصولی محدودیت‌های آپلود

اگر مقصر محدودیت PHP است، سه روش برای افزایش دارید. ترتیب توصیهٔ من بر اساس پایداری است:

روش اول — از طریق php.ini یا پنل هاست: پایدارترین روش. اگر به پنل هاست دسترسی دارید، از بخش «MultiPHP INI Editor» یا مشابه، مقدارها را تنظیم کنید:

upload_max_filesize = 64M
post_max_size = 128M
memory_limit = 256M
max_execution_time = 300
max_input_time = 300

روش دوم — از طریق .user.ini: در بعضی هاست‌ها که php.ini در دسترس نیست، می‌توانید یک فایل .user.ini در ریشهٔ سایت بسازید که همان مقادیر را تنظیم کند:

upload_max_filesize = 64M
post_max_size = 128M
memory_limit = 256M

روش سوم — از طریق .htaccess: فقط در هاست‌هایی که AllowOverride اجازه دهد:

php_value upload_max_filesize 64M
php_value post_max_size 128M
php_value max_execution_time 300

یک نکتهٔ کاربردی: برخی از افزونه‌های امنیتی و مدیریتی، این مقادیر را در پیشخوان نمایش می‌دهند و می‌توانید مستقیماً ببینید که تنظیمات اعمال شده یا نه. در تجربه‌ام، روش اول پایدارترین است، روش دوم در اکثر هاست‌های مدرن کار می‌کند و روش سوم شکننده‌تر است.

رفع مشکل مجوز پوشهٔ uploads

اگر مقصر مجوز پوشه است، کار ساده است — ولی باید درست انجام شود:

  1. از طریق FTP یا File Manager، به wp-content بروید.
  2. روی پوشهٔ uploads راست‌کلیک کنید و گزینهٔ Permissions را انتخاب کنید.
  3. مجوز را روی 755 تنظیم کنید. هرگز 777 — چون یک ریسک امنیتی جدی است. اگر پوشهٔ uploads وجود ندارد، آن را بسازید.
  4. همین کار را برای زیرپوشه‌های داخل uploads (سال/ماه) هم انجام دهید.
  5. اگر بعد از این تغییر هم خطا داشتید، مسئله مالکیت است. از پشتیبانی هاست بخواهید مالکیت فایل‌ها را با کاربر وب‌سرور هم‌راستا کند.

در پروژه‌های خودم، اگر هاست اجازه دهد، از طریق SSH این کار را سریع‌تر انجام می‌دهم:

find /path/to/wp-content/uploads -type d -exec chmod 755 {} \;
find /path/to/wp-content/uploads -type f -exec chmod 644 {} \;

مبانی کامل مدل مجوز و مالکیت در رفع خطای Permission در وردپرس آمده؛ آن مقاله توضیح می‌دهد چرا 755 برای پوشه و 644 برای فایل، استاندارد طلایی است.

مجاز کردن فرمت‌های خاص در وردپرس

اگر می‌خواهید فرمت‌هایی مثل SVG، ZIP یا فرمت‌های اختصاصی را در وردپرس مجاز کنید، از فیلتر upload_mimes استفاده کنید. نمونهٔ کد زیر را می‌توانید در چایلد تم خود یا در یک افزونهٔ اختصاصی اضافه کنید:

function wpkar_allow_custom_mimes( $mimes ) {
    $mimes['svg']  = 'image/svg+xml';
    $mimes['zip']  = 'application/zip';
    $mimes['rar']  = 'application/x-rar-compressed';
    return $mimes;
}
add_filter( 'upload_mimes', 'wpkar_allow_custom_mimes' );

هشدار مهم: مجاز کردن SVG به‌تنهایی خطرناک است، چون فایل SVG می‌تواند حاوی کد جاوااسکریپت باشد که در مرورگر کاربر اجرا شود. اگر حتماً به SVG نیاز دارید، بهتر است از افزونه‌ای استفاده کنید که SVG را قبل از ذخیره، پاک‌سازی (sanitize) کند. برای ZIP و RAR، توصیه می‌کنم در یک پوشهٔ محافظت‌شده ذخیره شوند یا از سرویس‌های فایل میزبانی خارجی استفاده کنید. مباحث امنیتی این تصمیم را در بهترین افزونه‌های امنیتی وردپرس باز کرده‌ام.

آپلود فایل‌های سنگین به‌روش‌های جایگزین

در بعضی سناریوها، فایل شما آن‌قدر سنگین است (مثلاً ویدئوی ۲۰۰ مگابایتی) که بالا بردن محدودیت PHP عملاً بی‌فایده است — چون هر آپلود، باید از مرورگر کاربر عبور کند و اگر اتصال قطع شود، آپلود از اول شروع می‌شود. سه راه‌حل جایگزین که در پروژه‌های خودم استفاده کرده‌ام:

  1. آپلود از طریق FTP: فایل را مستقیم در پوشهٔ uploads بگذارید و سپس از طریق یک افزونه، آن را به کتابخانهٔ رسانه «وارد» کنید.
  2. استفاده از افزونه‌های chunked upload: این افزونه‌ها فایل را به قطعات کوچک (چند مگابایتی) تقسیم می‌کنند و هر قطعه را جداگانه آپلود می‌کنند. اگر اتصال قطع شود، فقط همان قطعه دوباره آپلود می‌شود.
  3. استفاده از سرویس میزبانی خارجی: فایل را در سرویس‌هایی مثل YouTube (برای ویدئو)، SoundCloud (برای صدا) یا Google Drive قرار دهید و در سایت، جاسازی کنید. این روش، فضای دیسک شما را هم آزاد می‌کند.

برای ویدئو، توصیهٔ من در سایت‌های معمول این است که هرگز فایل ویدئویی را مستقیم در هاست هاست اشتراکی نگه ندارید — چون هم فضا می‌گیرد و هم پهنای‌باند را سریع تمام می‌کند. اگر هاست‌تان منابع کافی ندارد، پیشنهاد می‌کنم تأثیر هاست بر سرعت سایت را ببینید؛ چون در برخی پروژه‌ها، مهاجرت به هاست مناسب‌تر، هزینه‌ای کمتر از خرید افزونه‌های گران‌قیمت آپلود دارد.

آپلود در وردپرس چندسایتی

اگر روی وردپرس چندسایتی (Multisite) کار می‌کنید، محدودیت‌ها یک لایه پیچیده‌تر می‌شوند. به‌طور پیش‌فرض، مدیر شبکه می‌تواند فرمت‌های مجاز را در سطح کل شبکه محدود کند. اگر آپلود یک سایت زیرمجموعه شکست می‌خورد درحالی‌که سایت اصلی مشکلی ندارد، مقصر احتمالاً یک سیاست در سطح شبکه است.

مسیر تشخیص: در پیشخوان شبکه، بخش «تنظیمات شبکه» را باز کنید و فرمت‌های مجاز را ببینید. اگر فرمت مورد نیاز شما در آن لیست نیست، در سطح شبکه اضافه‌اش کنید. این کار احتیاط بیشتری می‌خواهد — چون هر تغییر در شبکه، روی همهٔ سایت‌های زیرمجموعه اثر می‌گذارد. در پروژه‌هایی که با مولتی‌سایت کار می‌کنم، همیشه تغییرات امنیتی در سطح شبکه را با تست در یک سایت آزمایشی شروع می‌کنم.

راستی‌آزمایی پس از رفع

بعد از اعمال رفع، سه لایه راستی‌آزمایی انجام دهید تا مطمئن شوید مسئله در ریشه حل شده است:

  1. تست آپلود همان فایل مقصر: دقیقاً همان فایلی که قبلاً شکست می‌خورد را دوباره آپلود کنید.
  2. تست آپلود چند فرمت متفاوت: یک تصویر، یک PDF، و یک فایل با فرمت اضافه‌شده.
  3. پایش پیشخوان به مدت ۲۴ ساعت: مطمئن شوید در طول روز، خطا برنمی‌گردد — چون بعضی خطاهای آپلود به‌خاطر فشار سرور در ساعات اوج ظاهر می‌شوند.

اگر مسئله در سرعت سایت هم اثر گذاشته — که در سایت‌هایی که آپلود سنگین دارند، شایع است — پیشنهاد می‌کنم بعد از رفع خطا، یک بار هم با ابزارهای سنجش سرعت، سه عدد کلیدی (TTFB، LCP، و حجم صفحه) را اندازه بگیرید. راهنمای عددی در Core Web Vitals چیست و در افزایش سرعت وردپرس آمده است.

اشتباهات رایج در مواجهه با خطای آپلود

اشتباهپیامدروش درست
تنظیم مجوز پوشه روی 777باز کردن درهای امنیتی سایتاستفاده از 755 برای پوشه‌ها
غیرفعال کردن افزونه‌های امنیتی بدون جایگزینحذف لایهٔ دفاعی سایتتنظیم دقیق فرمت‌های مجاز در افزونه
افزایش بی‌محدودیت حجم بدون بررسی سرورخطای ۵۰۰ یا کندی شدیدافزایش متناسب با منابع سرور
تغییر تنظیمات از چند مسیر (php.ini و .htaccess)تناقض و نامشخص‌بودن مقصرهر بار یک مسیر، یک تست
آپلود فایل سنگین بدون بخش‌بندیشکست در نیمهٔ راه، پر شدن حافظهchunked upload یا FTP

یک اشتباه ظریف که در دیدگاه‌ها زیاد می‌بینم: کاربران، فرض می‌کنند «خطای آپلود، حتماً یک مسئلهٔ امنیتی است» و سعی می‌کنند از طریق تغییرات عظیم امنیتی حلش کنند. در تجربهٔ من، بیش از هفتاد درصد موارد، ساده‌ترین ریشهٔ ممکن است: یک پارامتر PHP که اشتباه تنظیم شده. پس اول ساده‌ترین احتمال را رد کنید.

پیشگیری بلندمدت

پنج عادت که در پروژه‌های خودم خطاهای آپلود را به حداقل رسانده‌اند:

  • مقادیر PHP را از همان ابتدا متناسب با نیاز سایت تنظیم کنید. انتظار نداشته باشید پیش‌فرض‌های ۲ مگابایتی برای همه کافی باشد.
  • پایش فضای دیسک را ماهانه انجام دهید. هرگز بالای هشتاد درصد ظرفیت نروید.
  • کتابخانهٔ رسانه را مرتب پاک‌سازی کنید. فایل‌های بی‌استفاده، هم فضا می‌گیرند و هم مدیریت را سخت‌تر می‌کنند.
  • برای فایل‌های سنگین، از سرویس میزبانی خارجی استفاده کنید. ویدئو و فایل صوتی سنگین، نباید در هاست اشتراکی باشند.
  • سیاست MIME را در افزونهٔ امنیتی خودتان آگاهانه تعریف کنید. اجازهٔ همه‌چیز، امنیت را پایین می‌آورد؛ اجازهٔ هیچ‌چیز، کاربردی است که می‌شکند.

و یک عادت مهم: هر بار که خطای آپلود را رفع کردید، ریشه‌اش را در یک دفترچه یا فایل مستندات پروژه ثبت کنید. دفعهٔ بعد که همان خطا در سایت دیگری ظاهر شد، از روی همان سند، در چند دقیقه حل می‌شود. تجربه‌ام این است که مستندسازی، بیشتر از هر ابزار، عمر یک توسعه‌دهنده را در پشتیبانی طولانی می‌کند.

نگاه عمیق‌تر: آپلود به‌مثابه یک عملیات پرخطر

برای مهندسینی که با وردپرس در سطح تولیدی کار می‌کنند، آپلود فایل یک عملیات ظاهراً ساده است که در واقع، یکی از پرخطرترین نقاط حمله در هر وب‌اپلیکیشن است. این جایگاه، سه نتیجهٔ معماری به دنبال دارد:

یک — مسیر آپلود، یک مرز امنیتی است نه یک رابط کاربری. هر فایلی که از بیرون وارد سیستم شما می‌شود، یک واحد غیرقابل‌اعتماد است تا زمانی که خلافش ثابت شود. الگوی درست، «اعتبارسنجی چند‌لایه» است: هم در سطح PHP (با MIME)، هم در سطح وردپرس (با لیست مجاز)، هم در سطح فایل ذخیره‌شده (با اسکن). در معماری‌های بالغ، این سه لایه با هم کار می‌کنند و هر کدام از یک زاویه، ریسک را کاهش می‌دهند. این همان منطقی است که در بحث بهترین افزونه‌های امنیتی وردپرس به آن اشاره کرده‌ام؛ لایه‌بندی، جایگزین‌ناپذیر است.

دو — جداسازی پوشهٔ uploads از مسیر اجرا. در معماری‌های امن، هرگز نباید پوشه‌ای که فایل کاربران در آن ذخیره می‌شود، اجازهٔ اجرای PHP داشته باشد. وردپرس به‌طور پیش‌فرض این کار را انجام نمی‌دهد، اما بهترین کار این است که در .htaccess یا پیکربندی Nginx، قوانینی اضافه کنید که اجرای PHP در پوشهٔ uploads را ممنوع کند. همچنین پوشهٔ uploads را روی یک دامنهٔ جداگانه (Subdomain) میزبانی کنید تا حتی اگر فایلی آپلود شد، از دامنهٔ اصلی نتواند به سشن کاربر دسترسی بگیرد. این الگو، استاندارد امروز در سیستم‌های مدیریت فایل حرفه‌ای است.

سه — استفاده از پردازش نامتقارن برای فایل‌های سنگین. آپلود مستقیم فایل از مرورگر به PHP، ذاتاً شکننده است: هر بار که اتصال قطع شود، تمام آپلود از اول شروع می‌شود. معماری مدرن، این مسئله را با جداسازی حل می‌کند: فایل مستقیم به یک فضای ذخیره‌سازی ابری (مثل S3 یا معادل داخلی) آپلود می‌شود و سپس با یک پیام asynchronous، به وردپرس اطلاع داده می‌شود. این الگو، هم فشار از روی سرور PHP را برمی‌دارد، هم مقاومت را در برابر قطعی اتصال بالا می‌برد. در پروژه‌هایی که با فایل‌های حجیم سر و کار دارند، این تفاوت بین «کاربر خسته از آپلود دوباره» و «تجربهٔ روان» است.

از منظر انتزاعی‌تر، آپلود فایل نمونه‌ای از یک input boundary در تئوری سیستم‌هاست — مرزی که در آن، داده‌ای از محیط بیرونی (که کنترل کامل روی آن ندارید) وارد سیستم شما می‌شود. استاندارد طلایی در این مرزها، سه اصل است: «هرگز اعتماد نکن»، «همیشه اعتبارسنجی کن»، و «ذخیره‌سازی را از پردازش جدا کن». وردپرس، با تمام سادگی‌اش، این سه اصل را در پیاده‌سازی پیش‌فرض خود دارد؛ اما مسئولیت ما به‌عنوان توسعه‌دهنده، این است که وقتی نیاز فراتر از پیش‌فرض می‌رود، همان اصول را با آگاهی از معماری بازسازی کنیم — نه اینکه با خاموش کردن لایه‌های دفاعی، راحتی لحظه‌ای را به قیمت آسیب‌پذیری بلندمدت بخریم.

آخرین نکته، از تجربهٔ میدانی

خطای آپلود فایل در وردپرس، بیش از آنکه یک مسئلهٔ فنی پیچیده باشد، یک مسئلهٔ کشف مسیر است. همان مسیر سه‌لایه‌ای که در ابتدای مقاله ترسیم کردم — PHP، وردپرس، افزونهٔ امنیتی — همیشه همهٔ جواب‌ها را در خودش دارد. اگر یاد بگیرید که هر خطا را در کدام لایه بجویید، این نوع خطا از یک تجربهٔ سردرگم‌کننده به یک تمرین تشخیصی قابل‌مدیریت تبدیل می‌شود.

اگر این خطا را روی سایت خودتان دیده‌اید و یکی از هشت ریشهٔ بالا مقصر بوده، خوشحال می‌شوم در دیدگاه‌ها بخوانم. به‌ویژه اگر سناریوی نادری کشف کرده‌اید — مثلاً یک افزونهٔ خاص که رفتار عجیبی داشته، یا یک سیاست سروری که کمتر دیده می‌شود — همان جزئیات، برای خوانندهٔ بعدی که در همان موقعیت گرفتار است، از هر راهنمای عمومی ارزشمندتر است. اگر هم پس از همهٔ این آزمایش‌ها به این نتیجه رسیدید که هاست فعلی سقف شماست، دو مقالهٔ راهنمای انتخاب هاست و تأثیر هاست بر سرعت سایت مسیر بعدی شما خواهند بود. 📁