Laravel İle Çoklu Dosya Sıkıştırma Ve Arşivleme Sistemi Nasıl Yapılır?

Laravel İle Çoklu Dosya Sıkıştırma Ve Arşivleme Sistemi Nasıl Yapılır?
Laravel İle Çoklu Dosya Sıkıştırma Ve Arşivleme Sistemi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Bu uygulamayı hayata geçirmek için sisteminizde PHP 8.2+ sürümünün yüklü olması ve Laravel projenizin hazır olması gerekir. PHP'nin standart kütüphanelerinden biri olan ZipArchive sınıfı, arşivleme işlemlerinin temelini oluşturur.

Öncelikle, sunucunuzda php-zip eklentisinin aktif olduğundan emin olun. Linux tabanlı sistemlerde şu komutla kontrol edebilirsiniz:

php -m | grep zip

Eğer çıktı boşsa, sudo apt install php-zip komutu ile eklentiyi yükleyip web sunucunuzu yeniden başlatmanız gerekecektir. Ayrıca, Laravel'in storage/app dizinine yazma izninizin olduğundan emin olun.

Adım Adım Arşivleme Mantığı

Arşivleme işlemi üç ana aşamadan oluşur: Dosyaların tespiti, ZIP dosyasının oluşturulması ve dosyaların bu arşive eklenmesi. Laravel'in Storage facade'ı (arayüzü), dosya sistemleriyle etkileşimi oldukça kolaylaştırır.

Aşağıdaki örnekte, belirli bir klasördeki dosyaları alıp geçici bir ZIP dosyasına dönüştüren temel yapıyı görebilirsiniz:

use ZipArchive;
use Illuminate\Support\Facades\Storage;

public function createArchive(array $files)
{
    $zip = new ZipArchive;
    $fileName = 'arsiv_' . time() . '.zip';
    $filePath = storage_path('app/public/' . $fileName);

    if ($zip->open($filePath, ZipArchive::CREATE) === TRUE) {
        foreach ($files as $file) {
            $zip->addFile(storage_path('app/' . $file), basename($file));
        }
        $zip->close();
    }

    return $filePath;
}

Bu kodda ZipArchive sınıfı başlatılır, CREATE bayrağı ile yeni bir dosya oluşturulur ve addFile metodu ile dosyalar arşivin içine yerleştirilir. İşlem sonunda close() çağrısı yapılarak dosya sistemine yazılması sağlanır.

Güvenli Dosya İndirme Yöntemleri

Kullanıcıya oluşturulan ZIP dosyasını sunarken doğrudan dosya yolu vermek yerine, Laravel'in response()->download() metodunu kullanmalısınız. Bu yöntem, dosyanın tarayıcıda doğru başlıklarla (headers) indirilmesini sağlar.

public function download(string $fileName)
{
    $path = storage_path('app/public/' . $fileName);

    if (!file_exists($path)) {
        abort(404, 'Dosya bulunamadı.');
    }

    return response()->download($path)->deleteFileAfterSend(true);
}

deleteFileAfterSend(true) metodu, dosya kullanıcıya başarıyla gönderildikten sonra sunucudan otomatik olarak silinmesini sağlar. Bu, disk alanınızın gereksiz dolmasını engellemek için kritik bir adımdır.

Kritik Güvenlik Uyarısı: Kullanıcıdan gelen dosya isimlerini asla doğrudan ZipArchive metodlarına parametre olarak geçmeyin. Mutlaka basename() kullanın veya dosya yollarını beyaz liste (whitelist) mantığıyla doğrulayın. Aksi takdirde "Path Traversal" (dizin geçişi) saldırılarına açık hale gelebilirsiniz.

Performans ve Ölçeklenebilirlik Karşılaştırması

Farklı dosya boyutları ve sayıları için kullanabileceğiniz yöntemleri aşağıda karşılaştırdık:

Yöntem Avantajı Dezavantajı
Senkron (Anlık) Basit kod yapısı Büyük dosyalarda zaman aşımı
Asenkron (Queue) Sunucuyu yormaz Kullanıcıya bildirim gerekir
Stream (Akış) Bellek dostu Implementasyonu daha karmaşık

Büyük Dosyalar İçin Kuyruk (Queue) Kullanımı

Eğer arşivlenecek dosya sayısı çok fazlaysa veya dosyalar büyükse, bu işlemi HTTP isteği içinde yapmak sunucunun "timeout" süresine takılmasına neden olur. Bu durumda Laravel Kuyruklarını (Queues) kullanmak en profesyonel yaklaşımdır.

// Job sınıfı içerisinde
public function handle()
{
    // Arşivleme işlemini burada gerçekleştirin
    // İşlem bitince kullanıcıya bildirim gönderin
}

Bu yapıda, kullanıcıya "İşlem başlatıldı, tamamlandığında size e-posta göndereceğiz" diyerek süreci arka plana atabilirsiniz. Kullanıcı deneyimi açısından bu, web uygulamanızın donmasını engeller.

Yaygın Hatalar ve Debug İpuçları

Geliştirme aşamasında en sık karşılaşılan hatalardan biri, ZipArchive nesnesinin dosyayı açamamasıdır. Bunun temel sebebi genellikle yanlış dosya yolları veya izin hatalarıdır.

  • Dosya Yolu Hatası: storage_path() kullandığınızdan emin olun, göreceli yollar bazen çalışma dizinine göre farklılık gösterebilir.
  • Bellek Sınırı: Çok büyük dosyalar için ini_set('memory_limit', '512M'); komutuyla geçici olarak bellek sınırını artırmanız gerekebilir.
  • İzinler: storage/app/public dizininin web sunucusu kullanıcısı (genellikle www-data) tarafından yazılabilir olduğunu kontrol edin.
Sorumluluk Reddi: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) dosya işleme süreçlerinde mutlaka dosya türü kontrolü (MIME type validation) yapın ve kötü niyetli dosyaların sisteme yüklenmesini engelleyin.

Sıkça Sorulan Sorular

ZipArchive sınıfı neden hata veriyor?

Genellikle PHP'nin zip eklentisi yüklü değildir veya dosya yolu geçersizdir. extension_loaded('zip') kontrolü yaparak eklentinin yüklü olduğunu doğrulayın.

Arşiv içindeki klasör yapısını nasıl korurum?

$zip->addFile($path, 'klasor_adi/' . $fileName); şeklinde ikinci parametrede dosyanın içindeki yolu belirterek hiyerarşiyi koruyabilirsiniz.

Çok büyük dosyaları nasıl sıkıştırırım?

Çok büyük dosyalar için ZipArchive yerine sistem komutlarını (örneğin exec('zip -r ...')) kullanmak bazen daha performanslı olabilir, ancak bu güvenlik riskleri nedeniyle dikkatli kullanılmalıdır.

İndirme bittikten sonra dosya neden silinmiyor?

deleteFileAfterSend(true) fonksiyonu sadece Symfony\Component\HttpFoundation\BinaryFileResponse nesneleri ile çalışır. Doğru dönüşü yaptığınızdan emin olun.

Parolalı ZIP dosyası oluşturabilir miyim?

PHP'nin standart ZipArchive kütüphanesi parola korumalı arşivlemeyi desteklemez. Bunun için harici paketler veya shell_exec üzerinden 7zip gibi araçlar kullanmanız gerekir.

Arşivleme Süreçlerinde Bellek Yönetimi ve İleri Optimizasyon

Laravel üzerinde çoklu dosya işlemleri yaparken en sık karşılaşılan sorun, PHP'nin memory_limit sınırına takılmaktır. Özellikle yüzlerce küçük dosyayı veya birkaç büyük dosyayı aynı anda belleğe yüklemeye çalışmak, sunucunun "Allowed memory size exhausted" hatası vermesine neden olur. Bu durumu aşmak için dosyaları doğrudan disk üzerinden stream ederek okumak ve geçici dizinleri verimli yönetmek kritiktir.

Aşağıdaki yöntem, büyük dosya listelerini belleği yormadan işlemek için bir Generator yapısı kullanır:

public function streamFilesToZip($files, $zipPath)
{
    $zip = new \ZipArchive();
    $zip->open($zipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);

    foreach ($files as $file) {
        // Dosyayı belleğe almadan stream olarak ekle
        $zip->addFile(storage_path('app/' . $file->path), $file->name);
    }

    $zip->close();
}

Alternatif Kütüphane: Zippy ile Daha Esnek Yapılar

ZipArchive sınıfı temel ihtiyaçlar için yeterli olsa da, karmaşık arşivleme senaryolarında (örneğin farklı sıkıştırma algoritmaları veya gelişmiş hata yönetimi) alchemy/zippy kütüphanesi profesyonel bir alternatif sunar. Zippy, arka planda zip, tar, gzip gibi araçları otomatik algılar ve daha temiz bir arayüz sağlar.

Kurulum ve kullanım örneği:

// Composer üzerinden kurulum: composer require alchemy/zippy
use Alchemy\Zippy\Zippy;

$zippy = Zippy::load();
$archive = $zippy->create('arsiv.zip', [
    'dosya1.pdf' => '/path/to/dosya1.pdf',
    'dosya2.jpg' => '/path/to/dosya2.jpg',
]);

// Arşiv içerisine yeni dosya ekleme
$archive->addMembers(['yeni_dosya.txt' => '/path/to/yeni_dosya.txt']);

Üretim Ortamında (Production) Güvenlik ve Temizlik Stratejileri

Arşivleme sistemlerinde en büyük risk, oluşturulan geçici dosyaların sunucuda birikerek disk alanını doldurmasıdır. Laravel'in Storage facade'ı ile bu dosyaları belirli bir süre sonra otomatik temizleyen bir "Cleanup Command" oluşturmak en iyi pratiktir.

Örnek Temizlik Komutu:

// app/Console/Commands/CleanOldArchives.php
public function handle()
{
    $files = Storage::files('temp_archives');
    foreach ($files as $file) {
        if (Storage::lastModified($file) < now()->subHours(24)->timestamp) {
            Storage::delete($file);
        }
    }
}

Bu komutu app/Console/Kernel.php içerisinde $schedule->command('archives:clean')->daily(); şeklinde tanımlayarak sunucunuzun her zaman temiz kalmasını sağlayabilirsiniz. Ayrıca, arşiv dosyalarını public dizini yerine storage/app/private altında tutmak, doğrudan URL üzerinden erişimi engelleyerek yetkisiz indirmelerin önüne geçer.

Sonuç

Laravel ile çoklu dosya sıkıştırma ve arşivleme sistemi kurmak, doğru araçları kullandığınızda oldukça basit ve güvenli bir süreçtir. Bu rehberde, temel arşivleme mantığından başlayarak, güvenli dosya indirme ve performans odaklı kuyruk yönetimine kadar kapsamlı bir yol haritası izledik. Bir sonraki adım olarak, oluşturulan bu arşivleri AWS S3 gibi bulut depolama servislerine yükleyerek sunucu yükünüzü daha da hafifletmeyi deneyebilirsiniz.

Bu yazıya tepkinizi paylaşın:
Deniz Aydın

On yıldır dijital yayıncılıkta pratik çözüm rehberleri hazırlıyorum. Karmaşık süreçleri herkesin anlayabileceği adım adım yönergelere dönüştürme konusunda uzmanım.

Yorumlar (0)

Yorum Yaz