18 β File storage va upload¶
β¬ οΈ Oldingi: 17 β RESTful API va Sanctum Β· π README Β· Keyingi: 19 β Mail va Notifications β‘οΈ
Bu bobda: foydalanuvchi yuklagan fayllar (avatar, mahsulot rasmi, PDF hujjat) bilan ishlashni o'rganamiz. Fayl upload formasini to'g'ri yozish, yuklangan faylni
image/mimes/maxbilan validatsiya qilish,store()vastoreAs()orqali xavfsiz saqlash, disklar tizimini (local,public,s3) tushunish,php artisan storage:linknima qilishini,Storagefacade'i bilan fayl o'qish/o'chirish/URL olish, S3-mos object storage (Contabo kabi) niendpointvapath-stylebilan ulash, hamda public va private (maxfiy) fayllarni farqlab, faylni xavfsiz yuklab berishni ko'rib chiqamiz.
Muammo¶
Profil sahifasiga "Rasm yuklash" tugmasi qo'ymoqchisiz. Foydalanuvchi rasm tanlaydi, "Saqlash" bosadi β va shu yerda savollar boshlanadi:
- Faylni qayerga qo'yamiz?
public/papkasiga tashlasak, brauzer ko'radi, lekin har qanday odam URL'ni topib, boshqaning hujjatini ko'rib oladi. - Faylni qanday nom bilan saqlaymiz? Ikki foydalanuvchi
rasm.jpgyuklasa, biri ikkinchisini o'chirib yuboradimi? - Yuklangan fayl haqiqatan rasm ekanini qanday tekshiramiz? Kimdir
.jpgdeb nomlagan virusni yuklasa-chi? - Ertaga sayt ikkita serverga bo'linsa, bir serverga yuklangan rasm ikkinchisida ko'rinmay qolsa nima bo'ladi?
Sof PHP'da bularning hammasini $_FILES, move_uploaded_file(), pathinfo() bilan qo'lda yozasiz β har bir loyihada qaytadan, har safar xavfsizlik teshigini qoldirish xavfi bilan. Laravel buni bitta yagona tushuncha β filesystem (disk) abstraksiyasi bilan hal qiladi. Siz "qaysi diskka saqla" deysiz, qolganini Laravel qiladi. Ertaga diskni local'dan s3'ga o'zgartirsangiz β kod o'zgarmaydi. Mana shu sehrni boshidan o'rganamiz.
Disk degani nima?¶
Laravel'da disk β fayllar saqlanadigan "joy". U serverdagi oddiy papka ham bo'lishi mumkin, AWS S3 yoki Contabo kabi bulutdagi server ham. Hammasi bitta faylda β config/filesystems.php da β sozlanadi. Standart Laravel loyihasida uchta muhim disk bor:
localβstorage/app/privateichida. Bu papka brauzerga ko'rinmaydi. Maxfiy fayllar: shartnomalar, hisobotlar, faqat ruxsati borlarga beriladigan hujjatlar shu yerda yashaydi.publicβstorage/app/publicichida. Bu fayllar brauzerga ochiq bo'lishi kerak (avatar, mahsulot rasmi). Lekin u hamstorage/ichida bo'lgani uchun, brauzer to'g'ridan-to'g'ri ko'rolmaydi β bunistorage:linkhal qiladi (pastda).s3β serverdan butunlay ajratilgan, bulutdagi object storage. Loyiha o'sganda yoki bir necha server ishlatganda zarur bo'ladi.
π Nega public/ papkasiga to'g'ridan-to'g'ri qo'ymaymiz? Chunki public/ β kodingiz bilan birga Git'da yuriydigan papka, foydalanuvchi yuklagan fayllar esa ma'lumot. Ularni aralashtirmaslik, va deploy paytida fayllar yo'qolmasligi uchun, Laravel ularni storage/ ga ajratadi. Tartib shu: kod public/ da, foydalanuvchi fayllari storage/ da.
π‘ Standart disk .env dagi FILESYSTEM_DISK bilan belgilanadi. Storage::put(...) deb disk nomini yozmasangiz, aynan shu standart disk ishlatiladi. Aniqlik uchun bu bobda biz har doim diskni ochiq yozamiz: Storage::disk('public')->....
Eng sodda upload: avatar yuklash¶
Yo'lni boshidan oxirigacha bitta misolda ko'raylik. Foydalanuvchi profilga avatar yuklaydi. Avval forma. Bu yerda bitta narsa majburiy: enctype="multipart/form-data". Busiz brauzer faylni jo'natmaydi, server faqat fayl nomini oladi:
<form action="/avatar" method="POST" enctype="multipart/form-data">
@csrf
<input type="file" name="avatar" accept="image/*">
@error('avatar')
<p style="color:red">{{ $message }}</p>
@enderror
<button type="submit">Yuklash</button>
</form>
π @csrf β har formada bo'lishi kerak (6-bobdan tanish). accept="image/*" β bu faqat brauzer darajasidagi qulaylik (fayl tanlash oynasida rasmlarni ko'rsatadi), xavfsizlik emas. Haqiqiy tekshiruv serverda, validatsiyada bo'ladi β busiz hech qachon ishonmang.
Endi kontroller. Mana upload oqimining yuragi:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class AvatarController extends Controller
{
public function store(Request $request)
{
$request->validate([
'avatar' => ['required', 'image', 'max:2048'],
]);
$yol = $request->file('avatar')->store('avatars', 'public');
$request->user()->update(['avatar' => $yol]);
return back()->with('xabar', 'Rasm yuklandi!');
}
}
Uchta qator β uchta ish. Birinchisi tekshiradi, ikkinchisi saqlaydi, uchinchisi bazaga yo'lni yozadi. Diqqat: bazaga faylning o'zi emas, uning diskdagi nisbiy yo'li (avatars/x9k3...jpg) yoziladi. Fayl diskda, baza esa "u qayerdaligini" biladi. Butun oqim mana shunday:
store('avatars', 'public') nima qiladi?
- Faylga tasodifiy, takrorlanmas nom beradi (masalan
x9k3lP2mQ.jpg) β ikki foydalanuvchi bir-birini o'chirib yubormaydi, va asl fayl nomidagi xavfli belgilar (../, bo'shliq) yo'qoladi. - Uni
publicdiskningavatars/papkasiga yozadi (ya'nistorage/app/public/avatars/). - Saqlangan nisbiy yo'lni qaytaradi β uni biz bazaga yozamiz.
π‘ ->store($papka, $disk) β birinchi argument papka, ikkinchisi disk. Diskni yozmasangiz, standart disk ishlatiladi. Avatar ochiq ko'rinishi kerak bo'lgani uchun biz 'public' ni ochiq yozdik.
Validatsiya: image, mimes, max¶
Upload xavfsizligi shu yerdan boshlanadi. Eng ko'p ishlatiladigan qoidalar:
$request->validate([
// Rasm: faqat rasm formatlari, eng ko'pi 2 MB
'avatar' => ['required', 'image', 'max:2048'],
// Aniq formatlar: faqat jpg, png, webp
'rasm' => ['required', 'mimes:jpg,jpeg,png,webp', 'max:4096'],
// Hujjat: PDF yoki Word, eng ko'pi 5 MB
'hujjat' => ['required', 'file', 'mimes:pdf,doc,docx', 'max:5120'],
// Rasm o'lchamlarini ham cheklash mumkin
'banner' => ['required', 'image', 'dimensions:min_width=800,min_height=400'],
]);
π max qiymati kilobaytda! max:2048 β 2048 KB = 2 MB. Bu ko'p adashtiradigan joy: max:2 deb yozsangiz, atigi 2 KB ruxsat berasiz va deyarli har rasm rad etiladi.
π image va mimes farqi:
- image β fayl umuman rasmmi (jpg, png, gif, webp...) tekshiradi. Diqqat: Laravel 11+ dan boshlab image qoidasi SVG'ni standart holda rad etadi (XSS xavfi sababli); SVG kerak bo'lsa, image:allow_svg deb aniq ruxsat berasiz.
- mimes:jpg,png β aniq formatlarni belgilaydi. Laravel buni fayl mazmuni (MIME turi) bo'yicha tekshiradi, faqat kengaytma bo'yicha emas. Ya'ni kimdir virus.exe ni rasm.jpg deb nomlasa, mimes baribir uni ushlaydi.
β Faqat kengaytmaga ishonish (sof PHP'da ko'p uchraydigan xato):
// Bu yetarli EMAS β kengaytmani har kim o'zgartira oladi:
if (str_ends_with($filename, '.jpg')) { /* ishonib saqlash */ }
β Laravel validatsiyasiga ishoning β u fayl mazmunini tekshiradi:
π‘ SVG β texnik jihatdan rasm, lekin ichida JavaScript bo'lishi mumkin (XSS xavfi). Foydalanuvchi avatari uchun SVG'ni ataylab ruxsat bermang: mimes:jpg,jpeg,png,webp deb aniq sanang.
storeAs β faylga o'zingiz nom berasiz¶
store() tasodifiy nom beradi. Ba'zan nomni o'zingiz boshqarishni xohlaysiz β masalan foydalanuvchi ID'si bilan:
$file = $request->file('hujjat');
// Nomni o'zimiz beramiz: papka, nom, disk
$nom = 'user-'.$request->user()->id.'-'.time().'.'.$file->extension();
$yol = $file->storeAs('hujjatlar', $nom, 'local');
π storeAs($papka, $nom, $disk) β uchta argument: papka, fayl nomi, disk. Diqqat: nomni o'zingiz tuzsangiz, takrorlanmasligiga o'zingiz javobgarsiz. time() yoki Str::uuid() qo'shish odat. Shubha bo'lsa β oddiy store() ishlating, u bu muammoni o'zi hal qiladi.
Yuklangan fayl haqida boshqa foydali ma'lumotlar:
$file = $request->file('hujjat');
$file->getClientOriginalName(); // foydalanuvchi yuklagan asl nom: "hisobot.pdf"
$file->extension(); // mazmun bo'yicha kengaytma: "pdf"
$file->getSize(); // hajmi baytda
$file->getMimeType(); // "application/pdf"
$file->hashName(); // tasodifiy nom (store() shuni ishlatadi)
π‘ getClientOriginalName() β bu foydalanuvchi bergan nom, unga ishonmang (xavfli belgilar bo'lishi mumkin). Uni faqat ko'rsatish (ekranda "siz hisobot.pdf yukladingiz" deyish) yoki bazada alohida ustunda saqlash uchun ishlating β diskdagi fayl nomi sifatida emas.
storage:link β public fayllarni brauzerga ochish¶
Avatar'ni public diskka saqladik, lekin u storage/app/public/ ichida β bu papka brauzerga ko'rinmaydi (faqat haqiqiy public/ papka ko'rinadi). Ko'prik kerak. Bitta buyruq buni hal qiladi:
Bu public/storage nomli symbolic link (ramka β bir papkaga ishora qiluvchi yorliq) yaratadi. U storage/app/public ga ishora qiladi. Endi storage/app/public/avatars/x.jpg fayli brauzerda https://sayt.uz/storage/avatars/x.jpg URL orqali ochiladi.
π Bu buyruqni har loyihada (va serverga deploy qilganda) bir marta ishga tushirish kerak. Unutsangiz, rasmlar saqlanaveradi, lekin brauzerda 404 chiqadi β eng ko'p uchraydigan "rasmim ko'rinmayapti" muammosining sababi shu.
π Windows'da symlink yaratish uchun terminalni administrator huquqi bilan ochish kerak bo'lishi mumkin. Ishlamasa, terminalni "Run as administrator" bilan qayta oching.
Endi Blade'da rasmni ko'rsatamiz. Ikki yo'l bor:
{{-- 1-yo'l: asset() yordamida (eng oddiy) --}}
<img src="{{ asset('storage/'.$user->avatar) }}" alt="Avatar">
{{-- 2-yo'l: Storage::url() (diskni o'zgartirsangiz ham ishlaydi) --}}
<img src="{{ Storage::url($user->avatar) }}" alt="Avatar">
π‘ Storage::url() ni afzal ko'ring. Ertaga diskni s3 ga o'zgartirsangiz, asset('storage/...') noto'g'ri URL beradi, Storage::url() esa avtomatik to'g'ri (bulutdagi) URL'ni qaytaradi. Blade ichida Storage facade'ini ishlatish uchun yuqorida use Illuminate\Support\Facades\Storage; shart emas β Blade kontekstida facade'lar global, lekin kontroller/klass ichida use qatori kerak.
Storage facade β fayllar bilan to'g'ridan-to'g'ri ishlash¶
$request->file()->store() β upload uchun qulay. Lekin fayl bilan keyinchalik (o'qish, o'chirish, tekshirish) ishlash uchun Storage facade'i bor. Eng kerakli metodlar:
use Illuminate\Support\Facades\Storage;
// Yozish (matn yoki kontent)
Storage::disk('public')->put('izohlar/eslatma.txt', 'Salom dunyo');
// O'qish
$matn = Storage::disk('public')->get('izohlar/eslatma.txt');
// Bormi?
if (Storage::disk('public')->exists('izohlar/eslatma.txt')) { /* ... */ }
// Hajmi
$hajm = Storage::disk('public')->size('izohlar/eslatma.txt');
// URL olish (public disk uchun)
$url = Storage::disk('public')->url('avatars/x.jpg');
// Nusxalash / ko'chirish
Storage::disk('public')->copy('izohlar/eslatma.txt', 'izohlar/nusxa.txt');
Storage::disk('public')->move('izohlar/nusxa.txt', 'arxiv/nusxa.txt');
// O'chirish
Storage::disk('public')->delete('avatars/eski.jpg');
π Bu metodlarning hammasi disk nomidan mustaqil ishlaydi. Storage::disk('s3')->put(...) deb yozsangiz, xuddi shu kod faylni bulutga yozadi β bironta ham qatorni o'zgartirmaysiz. Mana shu β disk abstraksiyasining butun kuchi.
Avatarni yangilaganda eskisini o'chirish β toza odat:
public function update(Request $request)
{
$request->validate(['avatar' => ['required', 'image', 'max:2048']]);
$user = $request->user();
// Eski avatar bo'lsa, uni o'chiramiz (axlat to'planmasin)
if ($user->avatar) {
Storage::disk('public')->delete($user->avatar);
}
$yol = $request->file('avatar')->store('avatars', 'public');
$user->update(['avatar' => $yol]);
return back()->with('xabar', 'Avatar yangilandi');
}
π‘ delete() mavjud bo'lmagan faylga chaqirilsa ham xato bermaydi β shuning uchun exists() bilan oldindan tekshirish shart emas. Lekin $user->avatar null bo'lishi mumkinligini tekshirish kerak (yuqoridagi if).
Private vs public fayl β xavfsizlik chizig'i¶
Bu bobning eng muhim qismi. Ikki xil fayl bor:
- Public fayl β hamma ko'rishi mumkin: avatar, mahsulot rasmi, blog rasmi.
publicdiskka saqlanadi, URL orqali ochiladi. - Private fayl β faqat ruxsati borlar ko'rishi kerak: foydalanuvchining shartnomasi, to'lov cheki, shaxsiy hujjat. Hech qachon
publicdiskka qo'ymang.
Private faylni local diskka saqlaymiz (u brauzerga umuman ochiq emas). Foydalanuvchi uni ko'rmoqchi bo'lsa, kontroller orqali, ruxsatni tekshirgandan keyin beramiz:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class HujjatController extends Controller
{
// Maxfiy hujjatni yuklab berish (faqat egasi)
public function download(Request $request, Hujjat $hujjat)
{
// 14-bobdan: avtorizatsiya tekshiruvi
if ($request->user()->isNot($hujjat->user)) {
abort(403);
}
return Storage::disk('local')->download($hujjat->yol, 'hisobot.pdf');
}
}
π Mantiq: fayl local diskda, ya'ni hech qanday URL bilan tashqaridan ochib bo'lmaydi. Yagona kirish yo'li β shu kontroller. Kontroller esa avval kim so'rayotganini tekshiradi (abort(403)), keyin faylni beradi. Mana shu β private fayl xavfsizligining butun mohiyati: fayl yashirin, kirish β faqat tekshiruvdan o'tib.
download va response farqi:
- Storage::disk('local')->download($yol, $nom) β brauzer faylni yuklab oladi (saqlash oynasi chiqadi). Ikkinchi argument β foydalanuvchi ko'radigan fayl nomi.
- Storage::disk('local')->response($yol) β fayl brauzerda ochiladi (masalan PDF'ni ko'rsatadi, yuklab olmaydi).
// Yuklab olish (Download tugmasi):
return Storage::disk('local')->download($yol, 'shartnoma.pdf');
// Brauzerda ko'rsatish (PDF'ni ochish):
return Storage::disk('local')->response($yol);
π‘ download($yol) da nom bermasangiz, diskdagi tasodifiy nom (x9k3.pdf) chiqadi. Foydalanuvchi tushunarli nom ko'rishi uchun ikkinchi argumentni doim bering.
S3 va S3-mos object storage¶
Loyiha o'sganda yoki bir nechta serverda ishlatganda, fayllarni serverda saqlash muammo bo'ladi: disk to'ladi, serverlar orasida fayl bo'linmaydi, deploy paytida yo'qoladi. Yechim β object storage: AWS S3, yoki uning arzonroq mosi (Contabo, DigitalOcean Spaces, MinIO). Ularning hammasi S3 protokoli bilan ishlaydi, demak Laravel uchun bir xil.
Avval S3 paketini o'rnatamiz (standart Laravel'da kelmaydi):
Keyin .env ga kalitlarni yozamiz. AWS uchun:
AWS_ACCESS_KEY_ID=sizning-kalitingiz
AWS_SECRET_ACCESS_KEY=sizning-maxfiy-kalitingiz
AWS_DEFAULT_REGION=eu-central-1
AWS_BUCKET=mening-bucket
S3-mos xizmat (masalan Contabo) uchun ikki qator qo'shimcha kerak β endpoint va path-style:
AWS_ACCESS_KEY_ID=sizning-kalitingiz
AWS_SECRET_ACCESS_KEY=sizning-maxfiy-kalitingiz
AWS_DEFAULT_REGION=eu2
AWS_BUCKET=mening-bucket
AWS_ENDPOINT=https://eu2.contabostorage.com
AWS_USE_PATH_STYLE_ENDPOINT=true
Bu kalitlar config/filesystems.php dagi s3 diskga ulanadi (bu disk standart loyihada allaqachon mavjud):
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'endpoint' => env('AWS_ENDPOINT'),
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
'throw' => false,
],
π Ikki muhim sozlama:
- endpoint β AWS'da yozmaysiz (Laravel o'zi biladi). Lekin Contabo/MinIO kabi xizmat boshqa manzilda turgani uchun, uning serverini ko'rsatish shart.
- use_path_style_endpoint β AWS bucket.s3.amazonaws.com ko'rinishidagi URL ishlatadi. Ko'p S3-mos xizmatlar esa endpoint/bucket ko'rinishini talab qiladi. Buni true qilmasangiz, fayllar topilmaydi. Contabo, MinIO uchun deyarli doim true.
Endi diskni s3 ga o'zgartirsangiz β qolgan kod butunlay o'zgarmaydi:
// Aynan o'sha store(), faqat disk 's3':
$yol = $request->file('avatar')->store('avatars', 's3');
// Aynan o'sha url():
$url = Storage::disk('s3')->url($yol);
π‘ Sinab ko'rish uchun lokal kompyuterda MinIO (bepul, Docker'da ishga tushadigan S3-mos server) ni o'rnatsangiz, S3 kodini AWS'ga pul to'lamasdan to'liq sinab ko'rasiz β kod bir xil bo'lgani uchun, ishlasa, AWS'da ham ishlaydi.
Private fayl S3'da β temporaryUrl¶
S3'dagi private faylga vaqtinchalik (masalan 5 daqiqa amal qiladigan) URL berish mumkin β havola tarqalib ketsa ham, muddati tugagach ishlamay qoladi:
π temporaryUrl() β S3 va S3-mos disklarda ishlaydi (local diskda emas). Bu private fayllarni samarali ulashishning eng ishonchli usuli: server faylni o'zidan o'tkazmaydi, foydalanuvchi to'g'ridan-to'g'ri bulutdan, lekin faqat muddat ichida oladi.
Rasm bilan ishlash (qisqacha)¶
Ko'pincha rasmni saqlashdan oldin uni kichraytirish kerak (avatar 4000px bo'lishi shart emas). Buning uchun mashhur paket β Intervention Image:
use Intervention\Image\Laravel\Facades\Image;
use Illuminate\Support\Facades\Storage;
$rasm = Image::read($request->file('avatar'))
->scaleDown(width: 400); // enini 400px ga, nisbatni saqlab
Storage::disk('public')->put(
'avatars/'.$request->file('avatar')->hashName(),
(string) $rasm->encode()
);
π‘ Bu β alohida paket, Laravel yadrosiga kirmaydi. Boshlang'ich loyihada rasmni qayta o'lchamasdan ham saqlasangiz bo'ladi; trafik o'sganda Intervention Image bilan kichraytirishni qo'shasiz. Hozir faqat shunday imkoniyat borligini bilib qo'ying.
Hammasini birlashtiramiz: to'liq oqim¶
Mahsulot rasmi yuklash β boshidan oxirigacha. Route:
use App\Http\Controllers\MahsulotController;
Route::get('/mahsulot/{mahsulot}/rasm', [MahsulotController::class, 'edit']);
Route::post('/mahsulot/{mahsulot}/rasm', [MahsulotController::class, 'store']);
Kontroller:
namespace App\Http\Controllers;
use App\Models\Mahsulot;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class MahsulotController extends Controller
{
public function store(Request $request, Mahsulot $mahsulot)
{
$request->validate([
'rasm' => ['required', 'image', 'mimes:jpg,jpeg,png,webp', 'max:4096'],
]);
// Eski rasmni o'chiramiz
if ($mahsulot->rasm) {
Storage::disk('public')->delete($mahsulot->rasm);
}
// Yangisini saqlaymiz, yo'lni bazaga yozamiz
$mahsulot->update([
'rasm' => $request->file('rasm')->store('mahsulotlar', 'public'),
]);
return back()->with('xabar', 'Rasm yangilandi');
}
}
Blade'da ko'rsatish:
@if ($mahsulot->rasm)
<img src="{{ Storage::url($mahsulot->rasm) }}" alt="{{ $mahsulot->nomi }}">
@else
<img src="{{ asset('img/standart.png') }}" alt="Rasm yo'q">
@endif
Mana β to'liq, xavfsiz, ko'chiriladigan upload oqimi. Forma faylni jo'natdi, validatsiya tekshirdi, store() xavfsiz nom bilan diskka yozdi, bazada yo'l saqlandi, Storage::url() ko'rsatdi. Diskni s3 ga o'zgartirsangiz β bu kodning birorta qatori o'zgarmaydi. Sof PHP'da har biri qo'lda, har loyihada qaytadan yoziladigan ishlarni Laravel bitta abstraksiya bilan hal qildi.
18-bob mashqlari¶
Quyidagi mashqlarni o'z loyihangizda (blog yoki do'kon) bajaring. Yechimlarini o'zingiz yozing β har biri oldingisidan bir qadam murakkabroq.
php artisan storage:linkni ishga tushiring vapublic/storageramkasi yaratilganini tekshiring (papkani oching vastorage/app/publicga ishora qilishini ko'ring).enctype="multipart/form-data"va@csrfbilan oddiy fayl upload formasi yozing;enctypeni olib tashlasangiz nima bo'lishini ko'ring (server faylni olmaydi).- Kontrollerda
$request->validate()bilanavatarustigarequired|image|max:2048qoidasini qo'ying; 3 MB rasm yuklab, xato xabari chiqishini tasdiqlang. - Validatsiya xatosini Blade'da
@error('avatar')bilan ko'rsating va eski qiymatni saqlash uchun forma holatini tekshiring. $request->file('avatar')->store('avatars', 'public')bilan rasmni saqlang va qaytgan nisbiy yo'lnidd()bilan ko'ring (tasodifiy nom berilganiga e'tibor bering).- Saqlangan yo'lni bazaga (
users.avatarustuni) yozing; migratsiya bilan ustun qo'shing vafillablegaavatarni qo'shing. - Blade'da yuklangan avatarni
Storage::url()bilan ko'rsating;asset('storage/'.$yol)bilan ham ko'rsatib, ikkalasining bir xil URL berishini solishtiring. storeAs()bilan faylni o'zingiz tuzgan nom (user-{id}-{time}.{ext}) bilan saqlang;extension()vagetClientOriginalName()qiymatlarinidd()bilan ko'ring.mimes:jpg,jpeg,png,webpqoidasini qo'llang va.gifrasm yuklab, rad etilishini tasdiqlang; keyinimageqoidasi bilan farqini taqqoslang.- Hujjat upload qoidasini yozing:
required|file|mimes:pdf,doc,docx|max:5120; 6 MB PDF yuklab,maxishlashini tekshiring. - Avatar yangilashda eski faylni
Storage::disk('public')->delete($eski)bilan o'chiring; o'chirishdan oldin va keyinStorage::exists()bilan tekshiring. Storage::disk('public')->put(),get(),size(),exists()metodlarini bitta marshrut ichida sinab, natijalarni ekranga chiqaring.Storage::disk('local')->put()bilan faylnilocaldiskka yozing; uni brauzerda URL orqali ochishga urinib, ko'rinmasligini (yashirinligini) tasdiqlang.- Maxfiy hujjatni
download()orqali beradigan marshrut yozing; ikkinchi argumentda tushunarli fayl nomi (hisobot.pdf) bering. - Xuddi shu faylni
response()bilan brauzerda ochadigan ikkinchi marshrut yozing;downloadvaresponsefarqini o'z ko'zingiz bilan ko'ring. - Private hujjatga ruxsat tekshiruvi qo'shing: faqat faylning egasi yuklab olsin, boshqalar
abort(403)olsin (14-bobdagi avtorizatsiyani eslang). composer require league/flysystem-aws-s3-v3ni o'rnating;.envga AWS kalitlarini (yoki MinIO/Contabo kalitlarini) yozing.- S3-mos xizmat uchun
.envgaAWS_ENDPOINTvaAWS_USE_PATH_STYLE_ENDPOINT=trueqo'shing;config/filesystems.phpdagis3diskda bu qiymatlarenv()orqali o'qilishini tekshiring. - Upload kodida diskni
'public'dan's3'ga o'zgartiring va boshqa kod o'zgarmaganini, faylning bulutga (yoki MinIO'ga) saqlanganini tasdiqlang. - S3'dagi private faylga
Storage::disk('s3')->temporaryUrl($yol, now()->addMinutes(5))bilan vaqtinchalik URL yarating; havolani 5 daqiqadan keyin ochib, ishlamasligini tekshiring.