Flutter & Mobil İle İleri Düzey Çoklu Dosya Sıkıştırma İşlemi Nasıl Yapılır?

Flutter & Mobil İle İleri Düzey Çoklu Dosya Sıkıştırma İşlemi Nasıl Yapılır?
Flutter & Mobil İle İleri Düzey Çoklu Dosya Sıkıştırma İşlemi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Bu işlemleri gerçekleştirmek için Flutter SDK sürüm 3.22 veya üzerinin yüklü olması önerilir. Projenizin pubspec.yaml dosyasına gerekli bağımlılıkları ekleyerek başlamalıyız. Dosya sıkıştırma işlemleri için Dart dilinin standart kütüphaneleri yetersiz kaldığında, archive paketi en güvenilir ve performanslı çözümdür.

Öncelikle terminalinizde şu komutu çalıştırarak gerekli paketi projenize dahil edin:

flutter pub add archive path_provider

archive paketi, ZIP, TAR ve GZIP gibi formatları desteklerken, path_provider ise mobil cihazın dosya sistemine erişim sağlamak için kullanılır. Bu kurulum tamamlandıktan sonra, uygulamanızın dosya okuma/yazma izinlerini (Android için AndroidManifest.xml, iOS için Info.plist) yapılandırmayı unutmayın.

Adım Adım Çoklu Dosya Sıkıştırma Mantığı

Çoklu dosya sıkıştırma işlemi, temel olarak her bir dosyanın belleğe okunması, bir Archive nesnesine eklenmesi ve ardından bu nesnenin sıkıştırılmış bir veri dizisine dönüştürülüp diske yazılması prensibine dayanır. Bellek yönetimi burada en kritik noktadır; çok büyük dosyaları aynı anda belleğe yüklemek, uygulamanın "Out of Memory" (OOM) hatası almasına neden olabilir.

İşte temel sıkıştırma fonksiyonunun yapısı:

import 'dart:io';
import 'package:archive/archive.dart';

Future compressFiles(List filePaths) async {
  final archive = Archive();
  for (var path in filePaths) {
    final file = File(path);
    if (await file.exists()) {
      final bytes = await file.readAsBytes();
      final filename = path.split('/').last;
      archive.addFile(ArchiveFile(filename, bytes.length, bytes));
    }
  }
  return ZipEncoder().encode(archive);
}

Bu kod bloğu, verilen dosya yollarını sırayla okur, Archive nesnesine ekler ve ZipEncoder kullanarak sıkıştırılmış bayt dizisini döndürür. Büyük dosya listelerinde bu işlemi compute fonksiyonu ile ana izlekten (main thread) ayırmak, arayüzün donmasını engeller.

İleri Düzey Performans Yönetimi: Isolate Kullanımı

Mobil cihazlarda sıkıştırma işlemi CPU yoğun bir iştir. Eğer 50-100 MB'lık dosyaları ana izlekte sıkıştırmaya çalışırsanız, kullanıcı arayüzü (UI) geçici olarak donacaktır. Flutter'ın compute fonksiyonu, bu tür ağır işlemleri arka plan izleklerinde (Isolate) çalıştırmanıza olanak tanır.

import 'package:flutter/foundation.dart';

// Arka planda çalışacak fonksiyon
List performCompression(List paths) {
  final archive = Archive();
  for (var path in paths) {
    final file = File(path);
    final bytes = file.readAsBytesSync();
    archive.addFile(ArchiveFile(path.split('/').last, bytes.length, bytes));
  }
  return ZipEncoder().encode(archive)!;
}

// UI kısmında çağrılışı
void startCompression(List paths) async {
  final compressedData = await compute(performCompression, paths);
  final file = File('path/to/output.zip');
  await file.writeAsBytes(compressedData);
}

Bu yöntem, sıkıştırma işleminin kullanıcı deneyimini bozmadan arka planda tamamlanmasını sağlar. compute kullanımı, Flutter uygulamalarında "Jank" (takılma) sorunlarını önlemek için standart bir yaklaşımdır.

Dosya Sıkıştırma Yöntemleri Karşılaştırması

Yöntem Avantaj Dezavantaj
ZipEncoder (Default) Evrensel uyumluluk Yüksek CPU kullanımı
TarEncoder Hızlı arşivleme Sıkıştırma oranı düşük
Isolate (Compute) UI donmaz Ek bellek yönetimi gerektirir

Güvenlik ve Hata Yönetimi

Dosya işlemleri yaparken güvenlik en öncelikli konudur. Kullanıcıdan alınan dosya yollarının doğrulanması ve yazma izinlerinin kontrol edilmesi gerekir. Ayrıca, sıkıştırma sırasında oluşabilecek disk doluluğu veya erişim hatalarını try-catch blokları ile yönetmelisiniz.

Kritik Uyarı: Uygulamanızda kullanıcı verilerini sıkıştırırken, hassas dosyaların (şifreler, özel anahtarlar vb.) geçici dizinlerde açıkta kalmadığından emin olun. Sıkıştırma bittikten sonra orijinal dosyaları veya geçici dosyaları file.delete() metodu ile temizlemeyi unutmayın.

try {
  final result = await compute(performCompression, filePaths);
  // Başarılı işlem
} on FileSystemException catch (e) {
  print('Dosya erişim hatası: ${e.message}');
} catch (e) {
  print('Beklenmedik hata: $e');
}

Sıkça Sorulan Sorular

Çok büyük dosyaları sıkıştırırken bellek hatası (OOM) alıyorum, ne yapmalıyım?

Büyük dosyaları belleğe tek seferde yüklemek yerine, dosyaları parçalar halinde (stream) okuyup arşivleme yöntemlerini araştırmalısınız. Ancak archive paketi genellikle küçük ve orta ölçekli dosyalar için optimize edilmiştir.

Sıkıştırılan dosyalara parola koyabilir miyim?

Standart archive kütüphanesi ZIP şifrelemesini doğrudan desteklemez. Parola korumalı bir arşiv oluşturmak için platforma özgü (Native) kütüphaneler kullanmanız veya şifreli bir dosya yapısı kurmanız gerekir.

İşlem sırasında uygulamanın arka planda kalması sıkıştırmayı durdurur mu?

Evet, mobil işletim sistemleri kaynak tüketimini azaltmak için arka plandaki uygulamaları durdurabilir. Uzun süreli sıkıştırma işlemleri için 'WorkManager' veya 'BackgroundFetch' gibi servisleri kullanmanız önerilir.

Hangi sıkıştırma formatı daha hızlıdır?

TAR formatı, dosyaları sadece paketlediği için (sıkıştırmadığı için) çok hızlıdır. Ancak dosya boyutunu küçültmek istiyorsanız ZIP veya GZIP tercih edilmelidir.

Flutter'da sıkıştırılmış dosyayı sunucuya nasıl gönderirim?

Sıkıştırılmış bayt dizisini MultipartFile olarak dio veya http kütüphaneleri ile sunucuya POST isteği atarak gönderebilirsiniz.

Sıkıştırma İşlemlerinde İleri Düzey Hata Ayıklama ve İzleme (Logging)

Büyük ölçekli dosya işlemlerinde, uygulamanın hangi aşamada tıkandığını veya hangi dosyanın sıkıştırma sırasında hata verdiğini anlamak kritik öneme sahiptir. Standart print komutları yerine, logger paketi ile seviyelendirilmiş bir izleme mekanizması kurmak, üretim ortamındaki hataları analiz etmenizi kolaylaştırır.

Aşağıdaki örnekte, sıkıştırma işlemini bir Stream yapısı ile sarmalayarak ilerleme durumunu ve hata detaylarını nasıl takip edebileceğinizi görebilirsiniz:

import 'dart:async';
import 'package:logger/logger.dart';

final logger = Logger();

Stream compressFilesWithProgress(List filePaths) async* {
  int total = filePaths.length;
  try {
    for (int i = 0; i < total; i++) {
      // Sıkıştırma mantığı burada çalışır
      logger.i("İşleniyor: ${filePaths[i]}");
      yield (i + 1) / total;
    }
  } catch (e) {
    logger.e("Sıkıştırma sırasında kritik hata: $e");
    throw Exception("Dosya işleme başarısız oldu.");
  }
}

Alternatif Yaklaşım: Native Platform Entegrasyonu (FFI)

Dart tabanlı archive kütüphanesi çoğu senaryo için yeterli olsa da, çok yüksek performans gerektiren (örneğin 4K video veya binlerce küçük dosya) durumlarda Dart'ın çalışma zamanı maliyeti yüksek gelebilir. Bu noktada Dart FFI (Foreign Function Interface) kullanarak C/C++ tabanlı libzip veya zlib kütüphanelerini doğrudan projenize dahil edebilirsiniz.

Neden FFI Tercih Edilmeli?

  • Bellek Yönetimi: C tarafında bellek yönetimi daha düşük seviyede kontrol edilebilir.
  • Hız: Native kod, Dart VM'in üzerinde ek bir katman olmadan doğrudan işlemci komutlarını çalıştırır.
  • Format Desteği: Dart kütüphanelerinin desteklemediği özel veya şifreli arşiv formatlarına erişim sağlar.

FFI kullanımı için pubspec.yaml dosyanıza ffi paketini eklemeniz ve ilgili platformun (Android için .so, iOS için .dylib) kütüphane dosyalarını projenize gömmeniz gerekir. Bu yöntem, özellikle dosya sistemi üzerinde yoğun işlem yapan kurumsal uygulamalar için önerilen ileri düzey bir mimari yaklaşımdır.

Performans Testi İçin İpucu

Sıkıştırma algoritmalarınızın performansını ölçmek için Stopwatch sınıfını kullanın. Farklı dosya boyutları için aşağıdaki gibi bir karşılaştırma tablosu oluşturarak uygulamanızın darboğazlarını belirleyebilirsiniz:

Dosya Boyutu Sıkıştırma Yöntemi Geçen Süre (ms)
10MB Dart Archive (Deflate) 450ms
10MB Native C (libzip) 120ms

Bu veriler ışığında, uygulamanızın kullanıcı deneyimini optimize etmek için hangi yöntemin daha uygun olduğuna karar verebilirsiniz. Küçük dosyalar için Dart kütüphaneleri yeterliyken, büyük veri setlerinde native çözümlere geçmek uygulamanızın "kilitlenme" (ANR) riskini minimize edecektir.

Sonuç

Flutter ile çoklu dosya sıkıştırma, uygulamanızın ağ trafiğini azaltmak ve veri yönetimini profesyonelleştirmek için harika bir yöntemdir. Bu makalede öğrendiğiniz archive paketi, compute ile izole çalışma mantığı ve hata yönetimi pratikleri, projelerinizde sağlam bir temel oluşturacaktır. Bir sonraki adım olarak, sıkıştırdığınız dosyaları dio kullanarak sunucuya yüklemeyi ve sunucu tarafında bu dosyaları nasıl açacağınızı inceleyebilirsiniz.

Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Üretim ortamına geçmeden önce dosya izinlerini, veri gizliliğini ve bellek sınırlarını kendi uygulama senaryonuza göre test etmeniz ve güvenlik denetimlerinden geçirmeniz gerekmektedir.

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

Yedi yıllık dijital içerik deneyimiyle karmaşık süreçleri herkesin anlayabileceği basit adımlara dönüştürüyorum. Pratik yaşam hackleri ve ev yönetimi konularında uzmanım.

Yorumlar (0)

Yorum Yaz