Supabase • المستوى الثالث • الدرس 3
العودة لفهرس المستوىتخزين الملفات والصور (Supabase Storage)
أهداف الدرس
- رفع الملفات بـ
storage.from().upload(). - الحصول على الرابط العام بـ
getPublicUrl(). - حذف الملفات بـ
remove()وعرضها بـlist(). - بناء Buckets وسياسات وصول آمنة.
1. ما هو Supabase Storage؟
Supabase Storage هو خدمة تخزين كائنية (Object Storage) مبنية على Amazon S3. يُستخدم لتخزين الملفات الكبيرة (صور، فيديو، PDF، ...) التي لا تُخزَّن عادةً في قاعدة البيانات.
- • Buckets — حاويات الملفات (مثل:
avatars،documents). - • Paths — مسار الملف داخل الـ Bucket (مثل:
user-101/avatar.png). - • Policies — قواعد الوصول (Public / Private / RLS).
javascript
// بنية التخزين
Storage
├── avatars/ ← Bucket (Public)
│ ├── user-101/
│ │ └── avatar.png ← ملف
│ └── user-102/
│ └── avatar.png
└── documents/ ← Bucket (Private)
└── user-101/
└── cv.pdf2. إنشاء Bucket من لوحة التحكم
قبل رفع الملفات، أنشئ Bucket من Supabase Dashboard → Storage → New Bucket:
Public Bucket
أي شخص يملك الرابط يمكنه القراءة.
مناسب: الصور الشخصية، المنتجات
Private Bucket
يتطلب RLS/Policy للوصول.
مناسب: المستندات، الملفات الحساسة
3. رفع الملفات — upload
لرفع ملف، استخدم .upload(path, file):
javascript
// رفع ملف بسيط
const { data, error } = await supabase.storage
.from('avatars')
.upload('user-101/avatar.png', file);
if (error) console.error(error);
else console.log('تم الرفع:', data.path);upsert: true
استبدال الملف إن وُجد.
upload(path, file, {
upsert: true
})contentType
تحديد نوع المحتوى.
upload(path, file, {
contentType: 'image/png'
})4. الحصول على الرابط — getPublicUrl
بعد الرفع، تحتاج رابطاً لعرض الملف في الـ UI:
javascript
// رابط عام (للبكتات العامة)
const { data } = supabase.storage
.from('avatars')
.getPublicUrl('user-101/avatar.png');
console.log(data.publicUrl);
// رابط موقَّع (للبكتات الخاصة)
const { data: signedData } = await supabase.storage
.from('documents')
.createSignedUrl('user-101/cv.pdf', 3600); // صالح لساعة
console.log(signedData.signedUrl);الفرق
- •
getPublicUrl— للبكتات العامة (Public). متزامن. - •
createSignedUrl— للبكتات الخاصة. غير متزامن (await).
5. الحذف والعرض والتنزيل
remove
حذف ملف أو عدة ملفات (يأخذ مصفوفة).
await supabase.storage
.from('avatars')
.remove(['path1', 'path2']);list
عرض ملفات داخل مجلد.
await supabase.storage
.from('avatars')
.list('user-101');download
تنزيل محتوى الملف كـ Blob.
const { data } = await supabase
.storage.from('avatars')
.download('user-101/a.png');move / copy
نقل/نسخ ملف.
await supabase.storage
.from('avatars')
.move('old.png', 'new.png');6. سياسات الوصول — Storage Policies
يمكنك حماية Bucket بقواعد RLS (مثل الجداول):
sql
-- سياسة: كل مستخدم يرفع صورته فقط
CREATE POLICY "Users upload own avatar"
ON storage.objects FOR INSERT
WITH CHECK (
bucket_id = 'avatars'
AND auth.uid()::text = (storage.foldername(name))[1]
);
-- سياسة: قراءة عامة للصور
CREATE POLICY "Public avatar read"
ON storage.objects FOR SELECT
USING (bucket_id = 'avatars');
-- سياسة: حذف الصورة لصاحبها فقط
CREATE POLICY "Users delete own avatar"
ON storage.objects FOR DELETE
USING (
bucket_id = 'avatars'
AND auth.uid()::text = (storage.foldername(name))[1]
);متغيرات مساعدة
- •
storage.foldername(name)— يُرجع مسار المجلد كمصفوفة - •
(storage.foldername(name))[1]— أول مجلد (UID المستخدم) - •
bucket_id— اسم الـ Bucket
التطبيق العملي
تحدي الدرس: نظام رفع صور كامل
- أضف
getPublicUrlلاستخراج رابط الملف. - أضف
deleteFileمعremove(). - أضف
listUserFilesمعlist(). - أضف
downloadFileمعdownload(). - أضف اختباراً تلقائياً.
⏳ جارٍ التحميل...