← رجوع

إدارة الملفات في Laravel باستخدام Storage و S3

R

UNIXMAN

Mar 17, 2026

Article Image

التخزين في Laravel: كيف يفكر النظام فعلًا (Local / S3 / MinIO)

أغلب الناس يتعامل مع storage في Laravel كأنه مجرد مكان لحفظ الملفات. ترفع صورة، تخزن ملف، وخلاص.

لكن بعد فترة، خصوصًا في المشاريع اللي فيها:

  • تحميل ملفات من المستخدمين
  • محتوى كبير (صور / فيديو)
  • تطبيق موزع بين أكثر من سيرفر

تكتشف أن موضوع التخزين ليس “مكان نحط فيه الملفات”، بل طبقة مستقلة لازم تفهمها صح.


كيف Laravel يتعامل مع التخزين

Laravel لا يتعامل مع التخزين مباشرة، بل يستخدم abstraction فوق أنظمة التخزين المختلفة.

المفتاح هنا هو:

Storage facade

سواء كنت تستخدم:

  • local disk
  • S3
  • MinIO

الكود نفسه يبقى تقريبًا ثابت.

Storage::put('files/test.txt', 'hello');

هذا السطر ممكن يكتب الملف:

  • على السيرفر المحلي
  • على AWS S3
  • على MinIO

بدون تغيير الكود.


ملف الإعدادات: config/filesystems.php

كل شيء يبدأ من هنا.

Laravel يعرّف مجموعة من الـ disks:


'default' => env('FILESYSTEM_DISK', 'local'),

وهذا يحدد التخزين الافتراضي.

مثال:


FILESYSTEM_DISK=s3

هنا كل عمليات التخزين ستذهب إلى S3.


التخزين المحلي (Local Storage)

أبسط حالة.


Storage::disk('local')->put('file.txt', 'data');

المسار الفعلي:

storage/app/file.txt

إذا أردت جعله public:


php artisan storage:link

وهذا ينشئ:

public/storage -> storage/app/public

المشكلة التي تظهر لاحقًا

التخزين المحلي يعمل جيدًا في البداية.

لكن مع الوقت:

  • إذا لديك أكثر من سيرفر → الملفات لن تكون مشتركة
  • إذا السيرفر حذف → البيانات تضيع
  • إذا الملفات كبيرة → الأداء يتأثر

وهنا تبدأ الحاجة إلى Object Storage مثل S3.


AWS S3: لماذا يستخدم فعليًا

S3 ليس مجرد “تخزين خارجي”.

هو:

  • قابل للتوسع بدون حد عملي
  • مبني للتعامل مع ملفات ضخمة
  • موزع (distributed)
  • يدعم CDN بسهولة

وهذا يجعله مناسب لأي تطبيق فيه:

  • رفع صور
  • ملفات المستخدمين
  • media

ربط Laravel مع AWS S3

أولًا تحتاج إعداد AWS:

  • Bucket
  • Access Key
  • Secret Key

ثم في .env:


FILESYSTEM_DISK=s3

AWS_ACCESS_KEY_ID=xxxx
AWS_SECRET_ACCESS_KEY=xxxx
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=your-bucket
AWS_URL=

Laravel جاهز للتعامل مع S3 مباشرة بدون أي package إضافي.


مثال رفع ملف إلى S3


$file = request()->file('image');

$path = Storage::disk('s3')->put('uploads', $file);

أو:


$path = $file->store('uploads', 's3');

هنا الملف لا يُحفظ على السيرفر نهائيًا.


الحصول على رابط الملف


$url = Storage::disk('s3')->url($path);

أو رابط مؤقت:


$url = Storage::disk('s3')->temporaryUrl(
    $path,
    now()->addMinutes(10)
);

وهذا مهم عندما لا تريد جعل الملفات public.


MinIO: بديل S3 لكن تحت سيطرتك

MinIO يعطيك نفس مفهوم S3، لكن على سيرفرك الخاص.

وهذا مهم إذا:

  • لا تريد الاعتماد على AWS
  • تحتاج تحكم كامل بالبيانات
  • تعمل في بيئة داخلية (internal infra)
تجربتي مع S3 Bucket باستخدام MinIO

فكرة مهمة: Laravel لا يفرق بين S3 و MinIO

طالما MinIO يدعم S3 API، Laravel يتعامل معه بنفس الطريقة.

الفرق فقط في الإعدادات.


ربط Laravel مع MinIO

في .env:


FILESYSTEM_DISK=s3

AWS_ACCESS_KEY_ID=User
AWS_SECRET_ACCESS_KEY=Pass#2030
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=my-bucket
AWS_ENDPOINT=http://127.0.0.1:9000
AWS_USE_PATH_STYLE_ENDPOINT=true

النقطة المهمة:

  • AWS_ENDPOINT يشير إلى MinIO
  • AWS_USE_PATH_STYLE_ENDPOINT=true ضروري

أخطاء شائعة مع MinIO

  • نسيان endpoint → Laravel يحاول الاتصال بـ AWS الحقيقي
  • عدم تفعيل path-style → الروابط لا تعمل
  • مشاكل CORS عند رفع الملفات من frontend
  • عدم ضبط permissions داخل bucket

الصلاحيات (Permissions): الجزء الذي يتجاهله كثير من الناس

سواء في S3 أو MinIO:

الملفات لها حالتين:

  • public
  • private

مثال:


Storage::disk('s3')->put('file.txt', 'data', 'public');

أو:


Storage::disk('s3')->put('file.txt', 'data', [
    'visibility' => 'private'
]);

الخطأ الشائع:

جعل كل شيء public بدون تفكير.

في الأنظمة الحقيقية:

  • ملفات المستخدم → private
  • الصور العامة → public

التعامل مع التخزين كطبقة مستقلة

المطور الجيد لا يربط الكود مباشرة بـ Storage.

بدل:

Storage::put(...)

يفضل:


class FileService {
    public function upload($file) {
        return Storage::disk('s3')->put('uploads', $file);
    }
}

ليش؟

  • تغيير نوع التخزين بدون تغيير كل المشروع
  • إضافة logic مثل naming / validation
  • اختبار أسهل

متى تختار كل نوع تخزين؟

  • Local: مشاريع صغيرة أو development
  • S3: production scalable
  • MinIO: تحكم كامل + بيئة خاصة

مشكلة حقيقية تظهر في المشاريع الكبيرة

رفع الملفات مباشرة من السيرفر يسبب:

  • ضغط على السيرفر
  • زيادة latency

الحل:

رفع الملفات مباشرة من frontend إلى S3 باستخدام signed URLs.

وهذا يقلل الضغط بشكل كبير.