آپلود فایل یکی از قابلیتهای رایج در بسیاری از پروژههای وب است. تقریباً هر سیستم واقعی ممکن است به دریافت فایل از کاربر نیاز داشته باشد؛ از تصویر پروفایل و عکس محصول گرفته تا فایلهای مربوط به سفارش، مدارک، فایلهای پروژه و اسناد کاربران.
در Laravel ابزارها و امکانات مختلفی برای پیادهسازی File Upload در اختیار توسعهدهنده قرار دارد. میتوان فایل ارسالشده را از Request دریافت کرد، آن را اعتبارسنجی کرد و سپس با استفاده از متدهایی مانند store() یا storeAs() در مسیر موردنظر ذخیره کرد.
در این مقاله یاد میگیریم چگونه در Laravel یک سیستم آپلود فایل استاندارد ایجاد کنیم، فایلها را اعتبارسنجی کنیم، تصاویر را دریافت کنیم، چند فایل را همزمان آپلود کنیم و در نهایت با خطاهای رایج این فرآیند آشنا شویم.
File Upload در Laravel چیست؟
File Upload در Laravel به فرآیندی گفته میشود که طی آن کاربر یک فایل را از طریق فرم HTML به برنامه Laravel ارسال میکند و برنامه آن فایل را دریافت، اعتبارسنجی و در محل مشخصی ذخیره میکند.
برای مثال فرض کنید یک فروشگاه اینترنتی با Laravel ساختهاید. هنگام ایجاد محصول ممکن است مدیر بخواهد تصویر محصول را آپلود کند.
فرآیند کلی به این شکل است:
کاربر
↓
فرم HTML
↓
HTTP Request
↓
Laravel Request
↓
اعتبارسنجی فایل
↓
ذخیره فایل
↓
ثبت مسیر فایل در Database
نکته مهم این است که معمولاً خود فایل را داخل Database ذخیره نمیکنیم. فایل در سیستم فایل یا فضای ذخیرهسازی قرار میگیرد و مسیر یا نام فایل در دیتابیس ذخیره میشود.
ساخت فرم آپلود فایل در Laravel
برای ارسال فایل، فرم HTML باید از multipart/form-data استفاده کند.
برای مثال:
<form action="/products" method="POST" enctype="multipart/form-data">
@csrf
<label for="image">تصویر محصول</label>
<input type="file" name="image" id="image">
<button type="submit">
ذخیره محصول
</button>
</form>
مهمترین قسمت این فرم عبارت زیر است:
enctype="multipart/form-data"
اگر این ویژگی وجود نداشته باشد، فایل به شکل صحیح همراه Request ارسال نمیشود.
همچنین در پروژه Laravel باید برای درخواستهای POST از CSRF Token استفاده کنیم:
@csrf
دریافت فایل در Laravel
بعد از ارسال فرم، میتوانیم فایل را از طریق شیء Request دریافت کنیم.
برای مثال در Controller:
use Illuminate\Http\Request;
public function store(Request $request)
{
$file = $request->file('image');
// ادامه پردازش فایل
}
در این مثال:
$request->file('image')
فایلی را که در فیلد image فرم ارسال شده است دریافت میکند.
بررسی وجود فایل با hasFile
قبل از پردازش فایل میتوانیم بررسی کنیم که آیا کاربر واقعاً فایلی ارسال کرده است یا خیر.
if ($request->hasFile('image')) {
$file = $request->file('image');
}
این روش زمانی کاربردی است که آپلود فایل اختیاری باشد.
برای مثال:
if ($request->hasFile('avatar')) {
// ذخیره تصویر پروفایل
}
اعتبارسنجی فایل در Laravel
یکی از مهمترین قسمتهای File Upload، اعتبارسنجی فایل است.
نباید هر فایلی را بدون بررسی از کاربر دریافت و ذخیره کنیم.
Laravel امکان استفاده از Ruleهای مختلف برای اعتبارسنجی فایلها را فراهم میکند.
برای مثال:
$request->validate([
'image' => 'required|file|max:2048',
]);
در این مثال:
requiredیعنی فایل باید ارسال شود.fileیعنی مقدار باید یک فایل معتبر باشد.max:2048حداکثر حجم فایل را محدود میکند.
مقدار max در این Rule برای فایل بر اساس کیلوبایت محاسبه میشود؛ بنابراین 2048 تقریباً معادل 2 مگابایت است.
محدود کردن نوع فایل
فرض کنید فقط میخواهیم فایلهای PDF دریافت کنیم.
میتوانیم از mimes استفاده کنیم:
$request->validate([
'document' => 'required|file|mimes:pdf|max:5120',
]);
در این حالت فایل باید PDF باشد و حداکثر حجم آن حدود 5 مگابایت خواهد بود.
اعتبارسنجی تصویر
برای آپلود تصویر میتوان از Rule مربوط به image استفاده کرد:
$request->validate([
'image' => 'required|image|max:2048',
]);
این Rule برای سناریوهایی مانند تصویر محصول، آواتار کاربر و تصویر مقاله کاربرد زیادی دارد.
محدود کردن فرمت تصاویر
اگر بخواهیم فقط فرمتهای مشخصی را قبول کنیم:
$request->validate([
'image' => 'required|image|mimes:jpg,jpeg,png,webp|max:2048',
]);
در این حالت فرمتهای موردنظر مشخص شدهاند و حجم فایل نیز محدود شده است.
استفاده از Allowlist برای فرمتهای مجاز، معمولاً انتخاب مناسبتری نسبت به پذیرفتن هر نوع فایل است.
اعتبارسنجی ابعاد تصویر
در پروژههایی که اندازه تصویر اهمیت دارد، میتوان ابعاد تصویر را نیز بررسی کرد.
برای مثال:
use Illuminate\Validation\Rule;
$request->validate([
'image' => [
'required',
'image',
'max:2048',
Rule::dimensions()
->minWidth(500)
->minHeight(500),
],
]);
این قابلیت میتواند برای پروژههایی که تصاویر باید حداقل اندازه مشخصی داشته باشند مفید باشد.
ذخیره فایل با store
بعد از اعتبارسنجی فایل، یکی از سادهترین روشها برای ذخیره آن استفاده از store() است.
$path = $request->file('image')->store('images');
در این مثال فایل داخل پوشه images ذخیره میشود و مسیر فایل به عنوان نتیجه برگردانده میشود.
میتوانیم مسیر ذخیرهشده را نیز در متغیر نگه داریم:
$path = $request->file('image')->store('products');
مثلاً نتیجه ممکن است چیزی شبیه این باشد:
products/AbCdEf123456.jpg
نام فایل توسط Laravel مدیریت میشود و لازم نیست خودمان برای هر فایل یک نام تصادفی تولید کنیم.
چرا بهتر است نام فایل را خودمان از نام اصلی فایل نگیریم؟
فرض کنید کاربر فایلی با نام زیر آپلود کند:
my-product-image.jpg
استفاده مستقیم از نام فایل کاربر همیشه انتخاب مناسبی نیست.
نام فایل ارسالی ممکن است:
- شامل کاراکترهای نامناسب باشد.
- باعث تداخل نام فایلها شود.
- اطلاعاتی درباره کاربر یا سیستم او داشته باشد.
- در بعضی سناریوها مشکلات امنیتی ایجاد کند.
به همین دلیل استفاده از نامهای تولیدشده توسط Laravel برای بسیاری از سناریوها انتخاب مناسبی است.
ذخیره فایل با storeAs
اگر بخواهیم نام فایل را خودمان مشخص کنیم، میتوانیم از storeAs() استفاده کنیم.
$path = $request->file('image')->storeAs(
'products',
'product-100.jpg'
);
در این حالت فایل با نام مشخصشده ذخیره میشود.
با این حال، در پروژههای واقعی بهتر است هنگام تولید نام فایل، احتمال تکراری شدن نام و همچنین ورودی کاربر را در نظر بگیریم.
دریافت نام اصلی فایل
Laravel امکان دریافت نام اصلی فایل را نیز فراهم میکند:
$originalName = $request->file('image')->getClientOriginalName();
همچنین میتوان اطلاعات دیگری مانند پسوند فایل را دریافت کرد.
اما نکته مهم این است که نام اصلی فایل کاربر را نباید بهعنوان یک داده قابل اعتماد در نظر بگیریم.
برای نمایش نام فایل به کاربر میتوان آن را ذخیره کرد، اما برای نامگذاری فیزیکی فایل بهتر است از روش امنتر و قابلکنترلتری استفاده شود.
دریافت پسوند فایل
برای دریافت پسوند فایل میتوان از:
$extension = $request->file('image')->extension();
استفاده کرد.
این مقدار میتواند برای برخی پردازشهای برنامه کاربردی باشد.
ذخیره فایل در پوشه مشخص
فرض کنید میخواهیم تصاویر محصولات را در پوشه products ذخیره کنیم:
$path = $request->file('image')->store('products');
برای تصاویر کاربران:
$path = $request->file('avatar')->store('avatars');
و برای فایلهای اسناد:
$path = $request->file('document')->store('documents');
این ساختار باعث میشود فایلهای پروژه منظمتر مدیریت شوند.
ذخیره فایل روی Disk مشخص
Laravel از مفهوم Disk برای مدیریت محل ذخیره فایلها استفاده میکند.
میتوان هنگام ذخیره فایل Disk موردنظر را مشخص کرد:
$path = $request->file('image')->store(
'products',
'public'
);
در این مثال فایل در Disk به نام public ذخیره میشود.
جزئیات کامل Filesystem و Diskها را در مقاله جداگانه Storage در Laravel بررسی خواهیم کرد.
لینک کردن Public Storage
در بسیاری از پروژههای Laravel از Disk عمومی برای فایلهایی استفاده میشود که باید از طریق مرورگر قابل دسترسی باشند.
برای ایجاد لینک Storage میتوان دستور زیر را اجرا کرد:
php artisan storage:link
این دستور لینک لازم برای دسترسی عمومی به فایلهای Storage را ایجاد میکند.
پس از آن، فایلهای مربوط به Disk عمومی میتوانند از طریق مسیر مناسب پروژه در دسترس باشند.
آپلود تصویر محصول؛ مثال عملی
فرض کنیم یک سیستم فروشگاهی داریم و میخواهیم تصویر محصول را آپلود کنیم.
Controller:
use Illuminate\Http\Request;
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'image' => 'required|image|mimes:jpg,jpeg,png,webp|max:2048',
]);
$imagePath = $request->file('image')->store(
'products',
'public'
);
// ذخیره محصول و مسیر تصویر
}
در این مثال ابتدا دادهها اعتبارسنجی میشوند:
$request->validate(...)
سپس تصویر دریافت میشود:
$request->file('image')
و در نهایت در مسیر مشخص ذخیره میشود:
store('products', 'public')
مقدار $imagePath نیز میتواند در Database ذخیره شود.
ذخیره مسیر فایل در Database
فرض کنید Model مربوط به محصول دارای فیلدی به نام image است.
میتوانیم مسیر فایل را ذخیره کنیم:
$imagePath = $request->file('image')->store(
'products',
'public'
);
$product = Product::create([
'name' => $request->name,
'image' => $imagePath,
]);
در Database بهتر است مسیر فایل را ذخیره کنیم، نه محتوای کامل فایل را.
برای مثال:
products/AbCdEf123456.webp
و هنگام نمایش، مسیر مناسب را برای ساخت URL استفاده کنیم.
آپلود چند فایل در Laravel
گاهی کاربر باید چند فایل را به صورت همزمان ارسال کند.
فرم:
<form action="/documents" method="POST" enctype="multipart/form-data">
@csrf
<input
type="file"
name="documents[]"
multiple
>
<button type="submit">
آپلود
</button>
</form>
در Controller میتوان فایلها را دریافت کرد:
foreach ($request->file('documents', []) as $file) {
$path = $file->store('documents', 'public');
}
برای چنین سناریویی بهتر است هر فایل نیز به صورت جداگانه اعتبارسنجی شود.
مثلاً:
$request->validate([
'documents' => 'required|array',
'documents.*' => 'file|mimes:pdf,doc,docx|max:5120',
]);
در این حالت هر عضو آرایه documents باید یک فایل مجاز باشد.
استفاده از Form Request برای اعتبارسنجی Upload
اگر منطق اعتبارسنجی فایل پیچیده باشد، بهتر است آن را از Controller جدا کنیم.
برای ساخت Form Request:
php artisan make:request StoreProductRequest
سپس در متد rules():
public function rules(): array
{
return [
'name' => [
'required',
'string',
'max:255',
],
'image' => [
'required',
'image',
'mimes:jpg,jpeg,png,webp',
'max:2048',
],
];
}
سپس Controller تمیزتر خواهد شد:
public function store(StoreProductRequest $request)
{
$imagePath = $request->file('image')->store(
'products',
'public'
);
// ادامه عملیات
}
این روش مخصوصاً در پروژههای بزرگ Laravel کاربرد زیادی دارد.
جایگزین کردن فایل قبلی هنگام ویرایش
فرض کنید مدیر تصویر یک محصول را تغییر میدهد.
در این حالت معمولاً باید:
- فایل جدید دریافت شود.
- فایل جدید اعتبارسنجی شود.
- فایل جدید ذخیره شود.
- مسیر جدید در Database ثبت شود.
- در صورت نیاز فایل قدیمی حذف شود.
یک نمونه ساده:
$newPath = $request->file('image')->store(
'products',
'public'
);
$product->update([
'image' => $newPath,
]);
برای حذف فایل قدیمی باید از امکانات Storage استفاده کنیم که در مقاله Storage در Laravel به شکل کاملتر بررسی خواهد شد.
حذف فایل آپلودشده
اگر دیگر به فایلی نیاز نداریم، بهتر است فایلهای بدون استفاده روی سرور باقی نمانند.
Laravel امکان مدیریت فایلها از طریق Storage را فراهم میکند.
برای مثال:
use Illuminate\Support\Facades\Storage;
Storage::disk('public')->delete($product->image);
بعد از حذف فایل، در صورت نیاز میتوان مقدار مربوط به مسیر فایل را نیز از Database حذف یا به مقدار جدید تغییر داد.
نکات امنیتی مهم در File Upload
آپلود فایل یکی از قسمتهایی است که نباید بدون توجه به امنیت پیادهسازی شود.
فقط فرمتهای موردنیاز را قبول کنید
اگر سیستم فقط به تصویر نیاز دارد، همه انواع فایل را قبول نکنید.
به جای:
'file'
در صورت نیاز میتوانید از محدودیتهایی مانند:
'image|mimes:jpg,jpeg,png,webp'
استفاده کنید.
حجم فایل را محدود کنید
یک کاربر نباید بتواند فایلهای بسیار بزرگ را بدون محدودیت روی سرور آپلود کند.
مثلاً:
'max:2048'
حداکثر حجم فایل را محدود میکند.
به اطلاعات ارسالشده توسط کاربر اعتماد نکنید
نام فایل، پسوند اعلامشده و اطلاعات ارسالشده از سمت Client نباید بهتنهایی مبنای تصمیم امنیتی باشند.
فایل را با Ruleهای مناسب Laravel اعتبارسنجی کنید و فقط انواع فایل موردنیاز برنامه را مجاز کنید.
فایلهای اجرایی را بدون دلیل قبول نکنید
اگر سیستم شما برای مثال فقط تصاویر محصول دریافت میکند، دلیلی برای قبول فایلهای اجرایی یا فرمتهای غیرضروری وجود ندارد.
اصل مهم این است:
> هرچه محدوده فایلهای مجاز محدودتر باشد، سطح حمله نیز کوچکتر خواهد بود.
فایلهای حساس را عمومی نکنید
همه فایلها نباید از طریق URL عمومی قابل دسترسی باشند.
برای مثال مدارک هویتی کاربران، قراردادها یا فایلهای خصوصی نباید مانند تصویر عمومی یک محصول مدیریت شوند.
در چنین سناریوهایی باید دسترسی فایل نیز توسط برنامه کنترل شود.
File Upload و Storage چه تفاوتی دارند؟
این دو موضوع به یکدیگر مرتبط هستند اما یکی نیستند.
File Upload بیشتر درباره دریافت فایل از کاربر است:
Request
↓
File
↓
Validation
↓
Store
اما Storage بیشتر درباره مدیریت محل و روش ذخیره فایلها است.
برای مثال:
- Disk
- Local Storage
- Public Storage
- مسیر فایل
- مدیریت فایلها
- حذف فایل
- مدیریت فضای ذخیرهسازی
- استفاده از Storageهای مختلف
بنابراین در این مقاله تمرکز ما روی فرآیند Upload بود و جزئیات Storage را میتوان در مقاله بعدی بررسی کرد.
خطاهای رایج در آپلود فایل Laravel
خطای اول: فراموش کردن multipart/form-data
اگر فرم این ویژگی را نداشته باشد:
enctype="multipart/form-data"
ممکن است فایل به شکل صحیح ارسال نشود.
خطای دوم: فراموش کردن CSRF
در فرمهای POST مربوط به Laravel معمولاً باید از:
@csrf
استفاده کنید.
خطای سوم: اعتبارسنجی نکردن فایل
این کار مناسب نیست:
$path = $request->file('image')->store('images');
بدون اینکه قبل از آن نوع و حجم فایل را بررسی کرده باشید.
بهتر است ابتدا:
$request->validate([
'image' => 'required|image|max:2048',
]);
را انجام دهید.
خطای چهارم: ذخیره فایل با نام ورودی کاربر
نباید بدون بررسی کافی نام ارسالشده توسط کاربر را مستقیماً به نام فایل فیزیکی تبدیل کنیم.
روشهایی مانند store() میتوانند تولید نام مناسب فایل را مدیریت کنند.
خطای پنجم: ذخیره فایل در Database
در اغلب پروژهها نیازی نیست محتوای فایل را مستقیماً در Database قرار دهید.
روش معمول این است:
File → Storage
Path → Database
این معماری مدیریت فایلها را سادهتر میکند.
یک نمونه کامل از آپلود فایل
در ادامه یک نمونه ساده و قابل استفاده در پروژه واقعی میبینیم.
Route
use App\Http\Controllers\ProductController;
Route::post('/products', [ProductController::class, 'store']);
Controller
namespace App\Http\Controllers;
use App\Models\Product;
use Illuminate\Http\Request;
class ProductController extends Controller
{
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'image' => [
'required',
'image',
'mimes:jpg,jpeg,png,webp',
'max:2048',
],
]);
$imagePath = $request->file('image')->store(
'products',
'public'
);
Product::create([
'name' => $request->name,
'image' => $imagePath,
]);
return back()->with(
'success',
'محصول با موفقیت ایجاد شد.'
);
}
}
Form
<form
action="/products"
method="POST"
enctype="multipart/form-data"
>
@csrf
<input
type="text"
name="name"
placeholder="نام محصول"
>
<input
type="file"
name="image"
>
<button type="submit">
ذخیره محصول
</button>
</form>
این نمونه بخش زیادی از فرآیند معمول آپلود تصویر در یک پروژه Laravel را پوشش میدهد.
نکات مهم برای پیادهسازی حرفهای File Upload
برای پروژههای واقعی بهتر است چند اصل را همیشه در نظر داشته باشید:
| موضوع | پیشنهاد |
|---|---|
| اعتبارسنجی | همیشه فایل را Validate کنید |
| حجم | برای فایل محدودیت تعیین کنید |
| نوع فایل | فقط فرمتهای موردنیاز را قبول کنید |
| نام فایل | ترجیحاً نام امن و کنترلشده ایجاد کنید |
| Database | معمولاً مسیر فایل را ذخیره کنید |
| فایل خصوصی | آن را Public نکنید |
| فایلهای قدیمی | هنگام جایگزینی، در صورت نیاز حذف شوند |
| چند فایل | هر فایل جداگانه اعتبارسنجی شود |
| امنیت | به اطلاعات Client اعتماد کامل نکنید |
| ساختار پروژه | منطق Validation را در Form Request قرار دهید |
جمعبندی
File Upload یکی از قابلیتهای پایه اما بسیار مهم در پروژههای Laravel است. در یک پیادهسازی استاندارد، فایل ابتدا از طریق فرم multipart/form-data ارسال میشود، سپس Laravel آن را از طریق Request دریافت میکند.
بعد از آن باید فایل اعتبارسنجی شود و محدودیتهایی مانند نوع، فرمت، حجم و در صورت نیاز ابعاد تصویر روی آن اعمال شود.
برای ذخیره فایل نیز متدهایی مانند:
store()
و:
storeAs()
در اختیار ما هستند.
در پروژههای واقعی بهتر است فایل را در Storage نگهداری کرده و مسیر آن را در Database ذخیره کنیم. همچنین فایلهای حساس نباید بدون کنترل دسترسی به صورت عمومی در دسترس قرار بگیرند.
اگر قصد دارید مدیریت فایل در Laravel را به شکل حرفهای یاد بگیرید، موضوع بعدی یعنی Storage در Laravel اهمیت زیادی دارد؛ زیرا در آن با Diskها، مسیرهای ذخیرهسازی، Public Storage و مدیریت فایلها به شکل عمیقتر آشنا میشویم.
سوالات متداول
آیا برای آپلود فایل در Laravel باید از multipart/form-data استفاده کنیم؟
بله. هنگام ارسال فایل از طریق فرم HTML باید از:
enctype="multipart/form-data"
استفاده کنید.
چگونه فایل را از Request دریافت کنیم؟
با متد file():
$file = $request->file('image');
چگونه وجود فایل را بررسی کنیم؟
میتوان از:
$request->hasFile('image')
استفاده کرد.
چگونه حجم فایل را محدود کنیم؟
مثلاً برای محدود کردن حجم به حدود 2 مگابایت:
'image' => 'required|file|max:2048'
چگونه فقط تصویر را قبول کنیم؟
میتوان از Rule image استفاده کرد:
'image' => 'required|image'
چگونه فایل را در Laravel ذخیره کنیم؟
یکی از سادهترین روشها:
$path = $request->file('image')->store('images');
آیا بهتر است نام اصلی فایل را ذخیره کنیم؟
برای نامگذاری فیزیکی فایل، بهتر است از روشهای کنترلشده استفاده شود و نام اصلی فایل کاربر مستقیماً مبنای نام فایل قرار نگیرد.
آیا باید فایل را داخل Database ذخیره کنیم؟
در اغلب پروژهها بهتر است خود فایل در Storage قرار بگیرد و مسیر یا نام فایل در Database ذخیره شود.
تفاوت File Upload و Storage در Laravel چیست؟
File Upload روی دریافت و اعتبارسنجی فایل تمرکز دارد، در حالی که Storage امکانات و ساختار مربوط به محل و نحوه ذخیره و مدیریت فایلها را پوشش میدهد.





