Gereksinimler ve Ön Hazırlık
Çoklu dosya sıkıştırma modülümüzü oluştururken, Flutter'ın sunduğu güçlü kütüphanelerden ve Dart'ın asenkron yapısından faydalanacağız. Başlamadan önce aşağıdaki bağımlılıkların projenizde kurulu olduğundan emin olun.
- Flutter SDK: 3.24 veya daha güncel bir sürüm.
- archive: Çoklu dosya formatlarını (ZIP, TAR) işlemek için temel kütüphane.
- flutter_image_compress: Görsel sıkıştırma işlemleri için donanım hızlandırmalı çözüm.
- path_provider: Cihaz üzerindeki dosya yollarına erişim için.
Projenizin pubspec.yaml dosyasına şu bağımlılıkları ekleyin:
dependencies:
flutter:
sdk: flutter
archive: ^3.6.1
flutter_image_compress: ^2.3.0
path_provider: ^2.1.2
Adım Adım Çoklu Dosya Seçimi ve Hazırlık
Sıkıştırma işlemine başlamadan önce, kullanıcıdan alınan dosyaların listesini yönetmemiz ve bu dosyaların geçici dizinlerdeki konumlarını doğrulamamız gerekir. Çoklu dosya seçimi için file_picker paketini kullanmak en verimli yöntemdir.
import 'package:file_picker/file_picker.dart';
Future pickMultipleFiles() async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
allowMultiple: true,
type: FileType.any,
);
return result?.files;
}
Bu fonksiyon, kullanıcının cihazından birden fazla dosyayı seçmesine olanak tanır. Seçilen dosyalar PlatformFile listesi olarak döner ve bu nesneler üzerinden dosya yolu (path) bilgisine erişebiliriz.
Görsel Dosyaları İçin İleri Düzey Sıkıştırma Stratejisi
Görselleri sıkıştırırken kalite kaybını minimize etmek ve işlem süresini kısaltmak için flutter_image_compress kullanacağız. Bu kütüphane, ana iş parçacığını (UI thread) dondurmamak için arka planda çalıştırılmalıdır.
import 'dart:io';
import 'package:flutter_image_compress/flutter_image_compress.dart';
Future compressImage(File file, String targetPath) async {
var result = await FlutterImageCompress.compressAndGetFile(
file.absolute.path,
targetPath,
quality: 85,
minWidth: 1024,
minHeight: 1024,
);
return result;
}
Burada quality parametresi görselin sıkıştırma oranını belirlerken, minWidth ve minHeight parametreleri görselin boyutlarını yeniden ölçeklendirerek bellek kullanımını ciddi oranda azaltır.
ZIP Arşivleme ile Çoklu Dosya Birleştirme
Seçilen tüm dosyaları tek bir paket haline getirmek için archive kütüphanesini kullanacağız. Bellek yönetimi açısından, çok büyük dosyaları doğrudan RAM'e yüklemek yerine akış (stream) mantığıyla ilerlemek önemlidir.
import 'package:archive/archive_io.dart';
Future createZipArchive(List files, String outputPath) async {
final encoder = ZipFileEncoder();
encoder.create(outputPath);
for (var file in files) {
encoder.addFile(file);
}
encoder.close();
}
Bu kod bloğu, verilen dosya listesini tek bir ZIP dosyasına dönüştürür. ZipFileEncoder sınıfı, disk üzerindeki dosyaları doğrudan okuyarak paketlediği için RAM üzerinde aşırı yüklenme oluşmasını engeller.
Performans Analizi ve Karşılaştırma Tablosu
Farklı sıkıştırma yöntemlerinin uygulama üzerindeki etkilerini anlamak için aşağıdaki tabloyu inceleyebilirsiniz:
| Yöntem | Avantajı | Dezavantajı |
|---|---|---|
| GZIP (Tekil) | Hızlı ve düşük RAM kullanımı | Birden fazla dosyada verimsiz |
| ZIP (Çoklu) | Dosya hiyerarşisini korur | Büyük dosyalarda CPU yoğun |
| Image Compress | Görsel boyutunda %80'e varan düşüş | Kalite kaybı riski |
Isolate Kullanımı ile UI Donmasını Engelleme
İleri düzey bir modülde, sıkıştırma işlemleri sırasında uygulamanın donmaması şarttır. Dart'ın Isolate yapısı, ağır işlemleri farklı bir işlemci çekirdeğine taşıyarak ana ekranın akıcı kalmasını sağlar.
import 'dart:isolate';
Future runCompressionInIsolate(List files) async {
final receivePort = ReceivePort();
await Isolate.spawn(heavyCompressionTask, {
'files': files,
'sendPort': receivePort.sendPort
});
}
void heavyCompressionTask(Map message) {
// Sıkıştırma mantığı burada çalışır
}
Bu yaklaşım, uygulamanızın "Not Responding" hatası vermesini engeller ve kullanıcıya işlem devam ederken bir yükleme çubuğu (Progress Indicator) göstermenize olanak tanır.
Kritik Güvenlik Uyarısı: Dosya sıkıştırma işlemleri sırasında kullanıcıdan alınan dosyaların yollarını doğrulamadan (path validation) işlem yapmayın. Dışarıdan gelen veya geçici dizinlerdeki dosyaların kötü amaçlı yazılım içermediğinden emin olmak için dosya uzantılarını ve boyutlarını mutlaka kontrol edin.
Sıkça Sorulan Sorular
Sıkıştırma sırasında neden bellek hatası (OOM) alıyorum?
Bellek hatası genellikle tüm dosyaların aynı anda belleğe (RAM) yüklenmesinden kaynaklanır. Dosyaları parçalar halinde işleyerek veya Stream kullanarak bu sorunu çözebilirsiniz.
Sıkıştırılan dosyaların kalitesini nasıl artırabilirim?
quality parametresini 85'in üzerine çıkarabilirsiniz; ancak bu durum dosya boyutunun artmasına neden olacaktır. İdeal denge genellikle 75-85 arasındadır.
Arka planda sıkıştırma yaparken işlem yarıda kesilirse ne olur?
İşlemi bir try-catch bloğu ile sarmalayın ve hata durumunda geçici dizinde kalan yarım dosyaları file.delete() metodu ile temizleyin.
ZIP dosyasına şifre ekleyebilir miyim?
archive kütüphanesi temel ZIP desteği sunar. Şifreli arşivleme için daha gelişmiş platforma özgü (native) kütüphaneler kullanmanız gerekebilir.
Bu modül iOS ve Android'de aynı performansı verir mi?
Evet, ancak dosya sistemi izinleri (Permissions) her iki platformda da farklı yönetilir. permission_handler paketini kullanarak gerekli izinleri aldığınızdan emin olun.
Sorumluluk Reddi: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) kullanmadan önce hata yönetimi, dosya güvenliği ve platforma özgü kısıtlamaları (iOS/Android) detaylıca test etmeniz önerilir.
İleri Düzey Hata Ayıklama ve Loglama Stratejileri
Çoklu dosya sıkıştırma işlemleri sırasında karşılaşılan en yaygın sorunlar; dosya erişim kısıtlamaları, geçici dizinlerin dolması veya bellek taşmalarıdır. Bu tür karmaşık süreçlerde, uygulamanın hangi aşamada başarısız olduğunu anlamak için merkezi bir loglama mekanizması kurmak kritiktir. Sadece try-catch blokları kullanmak yerine, her sıkıştırma işlemini bir "İşlem Kimliği" (Transaction ID) ile takip etmelisiniz.
Aşağıdaki kod örneği, sıkıştırma sürecindeki adımları izlemek ve hata anında detaylı rapor oluşturmak için kullanabileceğiniz bir yapı sunar:
class CompressionLogger {
static void logStep(String step, String transactionId) {
print('[COMPRESSION_LOG][$transactionId]: $step - ${DateTime.now()}');
}
static void logError(dynamic error, String transactionId) {
// Hata raporlama servisinize (Sentry, Firebase Crashlytics vb.) veri gönderin
print('[COMPRESSION_ERROR][$transactionId]: $error');
}
}
// Kullanım örneği:
Future compressFiles(List files, String id) async {
try {
CompressionLogger.logStep('Sıkıştırma başlatıldı', id);
// Sıkıştırma mantığı burada çalışır...
} catch (e) {
CompressionLogger.logError(e, id);
rethrow;
}
}
Büyük Ölçekli Dosya Yönetimi İçin İleri İpuçları
Uygulamanız yüzlerce dosyayı aynı anda işliyorsa, işletim sistemi dosya tanımlayıcılarını (file descriptors) sınırlayabilir. Bu durumu yönetmek için "Chunking" (parçalara bölme) stratejisini uygulamak en sağlıklı yöntemdir. Tüm dosyaları belleğe yüklemek yerine, dosyaları belirli paketler halinde (örneğin 10'arlı gruplar) işleyerek sistem kaynaklarını koruyabilirsiniz.
Bellek Verimliliği İçin Akış (Stream) Kullanımı
Dosyaları okurken File.readAsBytesSync() yerine Stream yapısını tercih etmek, özellikle düşük donanımlı Android cihazlarda uygulamanın "Force Close" yemesini engeller. Dosyayı parçalar halinde okuyup sıkıştırma tamponuna (buffer) aktarmak, bellek tüketimini sabit tutar.
| Yöntem | Bellek Kullanımı | Hız | Uygunluk |
|---|---|---|---|
| Sync (Senkron) | Çok Yüksek | Hızlı | Küçük dosyalar |
| Async (Asenkron) | Orta | Orta | Orta ölçekli dosyalar |
| Stream (Akış) | Düşük | Yavaş | Büyük ölçekli dosyalar |
Bu stratejileri uygularken, path_provider paketi ile oluşturduğunuz geçici dizinleri (temporary directory) işlem sonunda mutlaka temizlemeyi unutmayın. Directory.delete(recursive: true) komutu, uygulamanın cihaz hafızasını şişirmesini önleyen en önemli güvenlik önlemidir.
Sonuç
Flutter ile çoklu dosya sıkıştırma modülü geliştirmek, uygulamanızın teknik kapasitesini bir üst seviyeye taşır. Bu rehberde dosya seçiminden, görsel optimizasyonuna ve asenkron iş parçacığı yönetimine kadar tüm adımları inceledik. Bir sonraki adım olarak, sıkıştırılan dosyaların sunucuya yüklenmesi (Multipart Upload) ve yükleme ilerlemesinin (Progress) kullanıcıya anlık olarak aktarılması konusunu araştırmanızı öneririm. Başarılar dilerim.


Yorumlar (0)
Yorum Yaz