Laravel İle Dinamik Dosya Yükleme Yönetimi Nasıl Yapılır?

Laravel İle Dinamik Dosya Yükleme Yönetimi Nasıl Yapılır?
Laravel İle Dinamik Dosya Yükleme Yönetimi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Dinamik dosya yönetimine başlamadan önce sisteminizde Laravel 11 veya üzeri bir sürümün kurulu olması önerilir. Dosya yükleme işlemlerinin sağlıklı çalışması için PHP'nin file_uploads ayarının açık olduğundan ve upload_max_filesize limitinizin yeterli olduğundan emin olmalısınız.

  • Laravel 11+ yüklü bir proje ortamı.
  • Dosya sistemlerini yönetmek için league/flysystem paketi (Laravel ile varsayılan gelir).
  • Dosya depolama için storage/app/public dizinine sembolik link (symlink) oluşturulmuş olmalıdır.

Sembolik linki oluşturmak için terminalinizde şu komutu çalıştırarak public klasörünüzün storage'a erişmesini sağlayın:

php artisan storage:link

Dosya Yükleme Formu ve İstek Doğrulama

Dosya yükleme işleminin ilk adımı, verinin güvenli bir şekilde sunucuya alınmasıdır. Laravel'de Request nesnesi üzerinden gelen dosyaları doğrulamak, güvenlik açıklarını (örneğin zararlı script yüklenmesi) engellemek için kritiktir.

Aşağıdaki örnekte, bir profil fotoğrafı yükleme işlemi için gerekli olan doğrulama kurallarını görebilirsiniz:

public function store(Request $request)
{
    $request->validate([
        'avatar' => 'required|image|mimes:jpeg,png,jpg,webp|max:2048',
    ]);

    // Dosya işleme mantığı buraya gelecek
}

Burada mimes ile sadece izin verilen formatları, max:2048 ile de dosya boyutunu 2MB ile sınırlandırmış olduk. Bu, sunucunuzu gereksiz büyük dosyalardan korur.

Dinamik Dosya İsimlendirme ve Kaydetme

Kullanıcıların yüklediği dosya isimleri genellikle tahmin edilebilir veya özel karakterler içerebilir. Güvenlik ve çakışmaları önlemek adına, dosyaları kaydederken benzersiz isimler atamak en iyi pratiktir. Laravel'in store metodu bu süreci otomatikleştirir.

public function upload(Request $request)
{
    if ($request->hasFile('avatar')) {
        $path = $request->file('avatar')->store('profiles', 'public');
        return response()->json(['path' => $path]);
    }
}

Bu kod bloğu, dosyayı storage/app/public/profiles klasörüne, benzersiz bir isimle kaydeder. store metodunun ikinci parametresi olan 'public', dosyanın web üzerinden erişilebilir olacağını belirtir.

Dosya Depolama Yöntemlerinin Karşılaştırılması

Laravel, dosya depolama konusunda esnek bir yapı sunar. Hangi depolama yöntemini seçeceğiniz, uygulamanızın ölçeğine ve bütçenize bağlıdır.

Yöntem Avantajı Dezavantajı
Local Disk Hızlı, maliyetsiz, kolay kurulum. Ölçeklenebilirlik düşük, sunucu değişince dosya taşınmalı.
Amazon S3 Sınırsız ölçeklenebilirlik, yüksek güvenlik. Ek maliyet, yapılandırma gerektirir.
Cloudinary Otomatik görsel optimizasyonu ve CDN. Üçüncü taraf bağımlılığı.

Dosya Silme ve Güncelleme İşlemleri

Dinamik bir yönetim sisteminde, sadece yükleme değil, eski dosyaların silinmesi de önemlidir. Kullanıcı yeni bir profil fotoğrafı yüklediğinde eski olanı silmek, disk alanından tasarruf sağlar.

use Illuminate\Support\Facades\Storage;

public function update(Request $request, User $user)
{
    if ($request->hasFile('avatar')) {
        // Eski dosyayı sil
        if ($user->avatar) {
            Storage::disk('public')->delete($user->avatar);
        }
        
        // Yeni dosyayı kaydet
        $path = $request->file('avatar')->store('profiles', 'public');
        $user->update(['avatar' => $path]);
    }
}

Bu örnekte, Storage::disk('public')->delete() metodu ile eski dosya sistemden temizlenir. Veritabanındaki yol güncellenerek tutarlılık sağlanır.

Kritik Güvenlik Uyarısı: Kullanıcıdan gelen dosya isimlerine asla güvenmeyin. Dosyaları kaydederken her zaman Laravel'in sağladığı store veya storeAs metodlarını kullanarak rastgele isimler oluşturun. Aksi takdirde, "Directory Traversal" saldırıları ile sunucu dosyalarınızın üzerine yazılabilir veya sistem dosyaları ifşa edilebilir.

Dosya Erişim Yönetimi ve Güvenlik

Özel dosyalar (faturalar, kişisel belgeler) public dizininde tutulmamalıdır. Laravel, storage/app/private dizininde tutulan dosyalara doğrudan erişimi engeller. Bu dosyalara erişmek için bir "download" rotası oluşturmanız gerekir.

Route::get('/download/{filename}', function ($filename) {
    return Storage::download('documents/' . $filename);
})->middleware('auth');

Bu yapı, sadece yetkili (giriş yapmış) kullanıcıların dosyayı indirmesine izin verir. middleware('auth') kullanımı, dosya güvenliği için olmazsa olmazdır.

Sıkça Sorulan Sorular

Dosya yükleme limitini nasıl artırabilirim?

PHP ayarlarınızdaki upload_max_filesize ve post_max_size değerlerini güncelleyerek bu limiti artırabilirsiniz. Ayrıca Laravel doğrulama kurallarında max:kilobyte değerini de güncellemeniz gerekir.

Neden dosyalarımı public klasörüne doğrudan koymuyorum?

public klasörü doğrudan web sunucusu tarafından erişilebilirdir. Güvenlik gerektiren dosyaları burada tutmak, herkesin dosyaya link ile erişebilmesi anlamına gelir. Laravel'in storage yapısı bu yüzden daha güvenlidir.

Dosyaları S3'e nasıl taşırım?

config/filesystems.php dosyasında S3 sürücüsünü yapılandırıp, .env dosyanıza AWS anahtarlarınızı girerek Storage::disk('s3')->put() komutuyla kolayca geçiş yapabilirsiniz.

Yüklenen dosyanın orijinal ismini nasıl korurum?

Eğer orijinal ismi korumanız gerekiyorsa storeAs metodunu kullanın, ancak dosya ismini Str::slug() gibi fonksiyonlarla temizleyerek güvenlik risklerini minimize edin.

Dosya yükleme sırasında hata alıyorum, ne yapmalıyım?

Öncelikle storage klasörünün yazma izinlerini (chmod 775) kontrol edin. Ardından storage/logs/laravel.log dosyasını inceleyerek spesifik hata mesajını görüntüleyin.

Sorumluluk Reddi: Bu makaledeki kod örnekleri genel eğitim amaçlıdır. Uygulamanızın canlı ortamında dosya yükleme süreçlerini devreye alırken, sunucu tarafındaki izinleri, dosya türü filtrelemelerini ve sunucu kaynak kısıtlamalarını (quota) mutlaka yapılandırın.

Büyük Dosyalar İçin Chunk (Parçalı) Yükleme Stratejisi

Laravel uygulamalarında özellikle video veya büyük veri setleri gibi yüksek boyutlu dosyaları yüklerken, PHP'nin upload_max_filesize ve post_max_size limitlerine takılmak yaygın bir sorundur. Bu engeli aşmak ve kullanıcı deneyimini iyileştirmek için dosyaları küçük parçalara bölerek sunucuya göndermek (Chunk Upload) en profesyonel yaklaşımdır.

Bu süreçte frontend tarafında Resumable.js veya Dropzone.js gibi kütüphaneler kullanılırken, backend tarafında Laravel ile parçaları birleştirmeniz gerekir. İşte basit bir parça birleştirme mantığı:

public function uploadChunk(Request $request)
{
    $receiver = new FileReceiver('file', $request, HandlerFactory::classFromRequest($request));

    if (!$receiver->isUploaded()) {
        return response()->json(['error' => 'Yükleme başarısız.'], 400);
    }

    $fileReceived = $receiver->receive();

    if ($fileReceived->isFinished()) {
        $file = $fileReceived->getFile();
        $path = $file->storeAs('uploads', $file->getClientOriginalName(), 's3');
        return response()->json(['path' => $path]);
    }

    $handler = $fileReceived->handler();
    return response()->json([
        'done' => $handler->getPercentageDone(),
        'status' => true
    ]);
}

Dosya Yükleme Süreçlerinde Performans Optimizasyonu

Dosya yükleme işlemleri sunucu kaynaklarını (CPU ve I/O) yoğun kullanan işlemlerdir. Uygulamanızın performansını korumak için aşağıdaki optimizasyon tekniklerini uygulamanız önerilir:

  • Asenkron İşleme: Kullanıcı dosyayı yükledikten sonra, dosya üzerinde yapılacak (resim boyutlandırma, PDF sıkıştırma gibi) işlemleri Laravel Queues kullanarak arka plana atın.
  • Resim Optimizasyonu: Kullanıcıların yüklediği görselleri orijinal boyutlarında saklamak yerine, Intervention Image kütüphanesi ile sunucu tarafında yeniden boyutlandırın.
  • CDN Kullanımı: Statik dosyalarınızı doğrudan sunucudan sunmak yerine, Cloudflare veya CloudFront gibi bir CDN (Content Delivery Network) üzerinden servis ederek sunucu yükünü azaltın.

Örneğin, bir görsel yüklendiğinde arka planda otomatik olarak thumbnail oluşturmak için şu yapıyı kullanabilirsiniz:

// App/Jobs/ProcessImage.php
public function handle()
{
    $image = Image::make(storage_path('app/' . $this->path));
    $image->resize(300, 200)->save(storage_path('app/thumbnails/' . $this->filename));
}

Otomatik Testler ile Dosya Yükleme Güvenliği

Dosya yükleme özelliklerinizi test ederken, sadece başarılı yüklemeleri değil, geçersiz dosya türlerini ve boş istekleri de test etmelisiniz. Laravel'in Illuminate\Http\UploadedFile sınıfı, test ortamında gerçek dosya yüklemeyi simüle etmek için mükemmeldir.

public function test_dosya_yukleme_validasyonu()
{
    Storage::fake('avatars');

    $file = UploadedFile::fake()->create('document.pdf', 500);

    $response = $this->post('/avatar', [
        'avatar' => $file,
    ]);

    Storage::disk('avatars')->assertExists('document.pdf');
    $response->assertStatus(200);
}

Bu test senaryosu, uygulamanızın dosya yükleme mantığının beklendiği gibi çalıştığını doğrular ve gelecekteki güncellemelerde oluşabilecek regresyon hatalarının önüne geçer.

Sonuç

Laravel ile dinamik dosya yükleme yönetimi, doğru yapılandırıldığında hem güvenli hem de oldukça esnektir. Bu rehberde dosya doğrulama, benzersiz isimlendirme, disk yönetimi ve yetkilendirme konularını ele aldık. Bir sonraki adım olarak, büyük boyutlu dosyaları arka planda (queue) işlemek veya Amazon S3 gibi bulut tabanlı bir depolama servisine entegrasyon yaparak uygulamanızın performansını ve ölçeklenebilirliğini artırabilirsiniz.

Bu yazıya tepkinizi paylaşın:
Selin Demir

Sürdürülebilir yaşam ve kişisel verimlilik üzerine odaklanan bir içerik üreticisiyim. Zaman yönetimi ve organizasyonel ipuçları konusunda okuyuculara yol gösteriyorum.

Yorumlar (0)

Yorum Yaz