البرمجة مبتدئ 9 دقيقة

كيفية رفع الملفات وتخزينها في Laravel

تجريد نظام الملفات في Laravel يجعل رفع الملفات أمرًا مباشرًا وقابلًا للتبديل. سواء كنت تخزّن الملفات محليًا، على القرص public، أو على Amazon S3، تعمل نفس واجهة store() مع جميع الـ drivers.

يأخذك هذا الدليل عبر الدورة الكاملة: نموذج HTML، التحقق من الصحة، تخزين الملف، إنشاء الرابط الرمزي العام، وعرض الرابط. ثم يتناول الانتقال إلى S3 عندما لا يعود القرص المحلي كافيًا.

الخطوات

  1. 1

    كتابة نموذج الرفع

    يجب أن يحتوي النموذج على enctype="multipart/form-data" — بدونه لن يُرسَل الملف الثنائي إلى الخادم أبدًا. استخدم التوجيه @csrf واضبط method="POST".

    html
    <form action="{{ route('upload.store') }}" method="POST" enctype="multipart/form-data">
        @csrf
        <input type="file" name="image" accept="image/*">
        @error('image')
            <p class="error">{{ $message }}</p>
        @enderror
        <button type="submit">Upload</button>
    </form>
  2. 2

    التحقق من صحة الملف المرفوع

    تحقق دائمًا من الصحة قبل التخزين. استخدم قاعدة file للتأكد من رفع شيء ما، وmimes للتقييد حسب الامتداد، وmax لتحديد حجم الملف بالكيلوبايت. يتحقق Laravel من امتداد الملف وNONE type المُبلَّغ عنه من المتصفح.

    php
    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    
    class UploadController extends Controller
    {
        public function store(Request $request)
        {
            $request->validate([
                'image' => [
                    'required',
                    'file',
                    'mimes:jpg,jpeg,png,webp,pdf',
                    'max:2048', // 2 MB
                ],
            ]);
    
            // proceed to store...
        }
    }
  3. 3

    تخزين الملف

    استدعِ $request->file('image')->store('uploads', 'public'). يولّد Laravel اسمًا فريدًا تلقائيًا (مبني على UUID)، ينقل الملف إلى storage/app/public/uploads/، ويُعيد المسار النسبي مثل uploads/abc123.jpg. احفظ ذلك المسار في قاعدة البيانات.

    إذا أردت التحكم في اسم الملف بنفسك، استخدم storeAs() بدلًا من ذلك.

    php
    // Auto-generated unique filename
    $path = $request->file('image')->store('uploads', 'public');
    // returns: "uploads/3f7a...uuid...jpg"
    
    // Custom filename
    $filename = time() . '_' . $request->file('image')->getClientOriginalName();
    $path = $request->file('image')->storeAs('uploads', $filename, 'public');
    
    // Save the path to the database
    $post = Post::create([
        'title' => $request->title,
        'image_path' => $path,
    ]);
  4. 4

    إنشاء الرابط الرمزي العام

    يخزّن القرص public الملفات في storage/app/public/، وهي غير متاحة عبر الويب افتراضيًا. شغّل php artisan storage:link مرة واحدة لإنشاء رابط رمزي من public/storage إلى storage/app/public. افعل هذا بعد النشر على كل خادم.

    bash
    php artisan storage:link
    # Creates: public/storage -> storage/app/public
  5. 5

    عرض الملف المخزّن

    استخدم دالة url() في واجهة Storage لتوليد الرابط العام من المسار المخزّن. تعمل مع قرص public (تُعيد رابطًا محليًا) ومع S3 (تُعيد رابط CDN أو S3).

    html
    {{-- In a Blade template --}}
    <img src="{{ Storage::disk('public')->url($post->image_path) }}" alt="Uploaded image">
    
    {{-- Or use the global helper --}}
    <img src="{{ asset('storage/' . $post->image_path) }}" alt="Uploaded image">
    
    {{-- In a controller or model --}}
    use Illuminate\Support\Facades\Storage;
    
    $url = Storage::disk('public')->url($post->image_path);
    // returns: https://yourdomain.com/storage/uploads/abc123.jpg
  6. 6

    فهم أقراص نظام الملفات

    يُعرّف config/filesystems.php في Laravel أقراصًا مسمّاة. الثلاثة الأكثر استخدامًا هي:

    • local — يخزّن الملفات في storage/app/، غير متاحة علنًا (جيد للوثائق الخاصة)
    • public — يخزّن في storage/app/public/، مرتبط رمزيًا بـ public/storage (جيد للصور وصور المستخدمين)
    • s3 — يخزّن على Amazon S3 (مستوى الإنتاج، يتوسع بلا حدود)

    تبدّل الأقراص بتغيير الوسيطة الثانية في store() أو باستدعاء Storage::disk('s3'). كود وحدة التحكم لا يتغير.

  7. 7

    ضبط قرص S3

    ثبّت محوّل Flysystem S3، ثم أضف بيانات AWS إلى .env. إعداد قرص S3 موجود بالفعل في config/filesystems.php — تحتاج فقط إلى تعبئة متغيرات البيئة.

    bash
    composer require league/flysystem-aws-s3-v3 "^3.0" --with-all-dependencies
  8. 8

    إضافة بيانات S3 إلى .env

    أضف ما يلي إلى ملف .env. AWS_URL اختياري — استخدمه إذا كان لديك توزيع CloudFront أمام الـ bucket حتى تُعيد Storage::url() رابط CDN بدلًا من رابط S3 المباشر.

    bash
    # .env
    AWS_ACCESS_KEY_ID=AKIA...
    AWS_SECRET_ACCESS_KEY=your-secret-key
    AWS_DEFAULT_REGION=us-east-1
    AWS_BUCKET=your-bucket-name
    AWS_URL=https://cdn.yourdomain.com  # optional, for CloudFront
    
    FILESYSTEM_DISK=s3  # make S3 the default disk
  9. 9

    الرفع إلى S3 وتوليد الرابط

    الآن استبدل اسم القرص في استدعاء store(). كل شيء آخر في وحدة التحكم يبقى كما هو. الملفات تصل إلى الـ bucket في S3 تحت البادئة uploads/.

    php
    // Store on S3
    $path = $request->file('image')->store('uploads', 's3');
    
    // Make the file publicly readable when uploading
    $path = $request->file('image')->storePublicly('uploads', 's3');
    
    // Generate the public URL
    $url = Storage::disk('s3')->url($path);
    // returns: https://your-bucket.s3.amazonaws.com/uploads/abc123.jpg

نصائح ومحاذير

  • لا تثق أبدًا باسم الملف المُرسَل من العميل — دع Laravel يولّده تلقائيًا، أو عقّمه بنفسك قبل استدعاء <code>storeAs()</code>. قد تحتوي الأسماء الأصلية على أحرف اجتياز المسار.
  • تحقق من نوع MIME من جانب الخادم باستخدام قاعدة <code>mimetypes</code> (مثلًا <code>mimetypes:image/jpeg,image/png</code>) لا فقط بالامتداد — الامتدادات سهلة التزوير.
  • للملفات الخاصة (عقود وفواتير)، خزّن على قرص <code>local</code> وقدّمها عبر وحدة تحكم تتحقق من التصريح — لا تستخدم قرص <code>public</code> للوثائق الحساسة أبدًا.
  • احذف الملفات القديمة عند استبدالها: <code>Storage::disk('public')->delete($post->image_path)</code> قبل حفظ المسار الجديد — وإلا سيمتلئ تخزينك بصمت.
  • على S3، استخدم Presigned URLs عبر <code>Storage::temporaryUrl($path, now()->addMinutes(5))</code> للملفات الخاصة بدلًا من جعل كامل الـ bucket عامًا.

خاتمة

أصبح بإمكانك الآن التعامل مع رفع الملفات من البداية إلى النهاية في Laravel — من تقديم النموذج المُتحقَّق منه إلى التخزين على القرص العام المحلي أو S3، وتوليد الرابط الصحيح للعرض. الخطوة الطبيعية التالية هي إضافة معالجة الصور (تغيير الحجم، القص، التحويل إلى WebP) باستخدام spatie/image أو intervention/image قبل تخزين الملف.

#Laravel #Files #S3
العودة إلى جميع الأدلة

هل تحتاج مساعدة في مشروعك؟

احجز استشارة مجانية لمدة 30 دقيقة لمناقشة تحدياتك التقنية واستكشاف الحلول معًا.