flutter_archive 4.0.1 flutter_archive: ^4.0.1 copied to clipboard
Create and extract ZIP archive files in Android, iOS and macOS. Zip all files in a directory recursively or a given list of files.
import 'dart:io';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter_archive/flutter_archive.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin test app'),
),
body: Center(
child: ElevatedButton(
onPressed: _test,
child: const Text("Test"),
),
),
),
);
}
final _appDataDir = Directory.systemTemp;
static const _dataFilesBaseDirectoryName = "store";
final _dataFiles = {
"file1.txt": "abc",
"file2.txt": "åäö",
"subdir1/file3.txt": r"@_£$",
"subdir1/subdir11/file4.txt": "123",
};
Future _test() async {
print("Start test");
// test createFromDirectory
// case 1
var zipFile = await _testZip(includeBaseDirectory: false, progress: true);
await _testUnzip(zipFile, zipIncludesBaseDirectory: false);
await _testUnzip(zipFile, progress: true);
// case 2
zipFile = await _testZip(includeBaseDirectory: true, progress: false);
await _testUnzip(zipFile, zipIncludesBaseDirectory: true);
// test createFromFiles
// case 1
zipFile = await _testZipFiles(includeBaseDirectory: false);
await _testUnzip(zipFile, zipIncludesBaseDirectory: false);
// case 2
zipFile = await _testZipFiles(includeBaseDirectory: true);
await _testUnzip(zipFile, zipIncludesBaseDirectory: true);
print("DONE!");
}
Future<File> _testZip(
{required bool includeBaseDirectory, bool progress = false}) async {
print("_appDataDir=${_appDataDir.path}");
final storeDir =
Directory("${_appDataDir.path}${"/$_dataFilesBaseDirectoryName"}");
_createTestFiles(storeDir);
final zipFile = _createZipFile("testZip.zip");
print("Writing to zip file: ${zipFile.path}");
int onProgressCallCount1 = 0;
try {
await ZipFile.createFromDirectory(
sourceDir: storeDir,
zipFile: zipFile,
recurseSubDirs: true,
includeBaseDirectory: includeBaseDirectory,
onZipping: progress
? (fileName, isDirectory, progress) {
++onProgressCallCount1;
print('Zip #1:');
print('progress: ${progress.toStringAsFixed(1)}%');
print('name: $fileName');
print('isDirectory: $isDirectory');
return ZipFileOperation.includeItem;
}
: null,
);
assert(!progress || onProgressCallCount1 > 0);
} on PlatformException catch (e) {
print(e);
}
return zipFile;
}
Future<File> _testZipFiles({required bool includeBaseDirectory}) async {
print("_appDataDir=${_appDataDir.path}");
final storeDir =
Directory("${_appDataDir.path}${"/$_dataFilesBaseDirectoryName"}");
final testFiles = _createTestFiles(storeDir);
final zipFile = _createZipFile("testZipFiles.zip");
print("Writing files to zip file: ${zipFile.path}");
try {
await ZipFile.createFromFiles(
sourceDir: storeDir,
files: testFiles,
zipFile: zipFile,
includeBaseDirectory: includeBaseDirectory);
} on PlatformException catch (e) {
print(e);
}
return zipFile;
}
Future _testUnzip(File zipFile,
{bool progress = false, bool zipIncludesBaseDirectory = false}) async {
print("_appDataDir=${_appDataDir.path}");
final destinationDir = Directory("${_appDataDir.path}/unzip");
final destinationDir2 = Directory("${_appDataDir.path}/unzip2");
if (destinationDir.existsSync()) {
print("Deleting existing unzip directory: ${destinationDir.path}");
destinationDir.deleteSync(recursive: true);
}
if (destinationDir2.existsSync()) {
print("Deleting existing unzip directory: ${destinationDir2.path}");
destinationDir2.deleteSync(recursive: true);
}
print("Extracting zip to directory: ${destinationDir.path}");
destinationDir.createSync();
// test concurrent extraction
final extractFutures = <Future>[];
int onExtractingCallCount1 = 0;
int onExtractingCallCount2 = 0;
try {
extractFutures.add(ZipFile.extractToDirectory(
zipFile: zipFile,
destinationDir: destinationDir,
onExtracting: progress
? (zipEntry, progress) {
++onExtractingCallCount1;
print('Extract #1:');
print('progress: ${progress.toStringAsFixed(1)}%');
print('name: ${zipEntry.name}');
print('isDirectory: ${zipEntry.isDirectory}');
print(
'modificationDate: ${zipEntry.modificationDate!.toLocal().toIso8601String()}');
print('uncompressedSize: ${zipEntry.uncompressedSize}');
print('compressedSize: ${zipEntry.compressedSize}');
print('compressionMethod: ${zipEntry.compressionMethod}');
print('crc: ${zipEntry.crc}');
return ZipFileOperation.includeItem;
}
: null));
extractFutures.add(ZipFile.extractToDirectory(
zipFile: zipFile,
destinationDir: destinationDir2,
onExtracting: progress
? (zipEntry, progress) {
++onExtractingCallCount2;
print('Extract #2:');
print('progress: ${progress.toStringAsFixed(1)}%');
print('name: ${zipEntry.name}');
print('isDirectory: ${zipEntry.isDirectory}');
print(
'modificationDate: ${zipEntry.modificationDate!.toLocal().toIso8601String()}');
print('uncompressedSize: ${zipEntry.uncompressedSize}');
print('compressedSize: ${zipEntry.compressedSize}');
print('compressionMethod: ${zipEntry.compressionMethod}');
print('crc: ${zipEntry.crc}');
return ZipFileOperation.includeItem;
}
: null));
await Future.wait<void>(extractFutures);
assert(onExtractingCallCount1 == onExtractingCallCount2);
assert(!progress || onExtractingCallCount1 > 0);
} on PlatformException catch (e) {
print(e);
}
// verify unzipped files
if (zipIncludesBaseDirectory) {
_verifyFiles(
Directory("${destinationDir.path}/$_dataFilesBaseDirectoryName"));
_verifyFiles(
Directory("${destinationDir2.path}/$_dataFilesBaseDirectoryName"));
} else {
_verifyFiles(destinationDir);
_verifyFiles(destinationDir2);
}
}
File _createZipFile(String fileName) {
final zipFilePath = "${_appDataDir.path}/$fileName";
final zipFile = File(zipFilePath);
if (zipFile.existsSync()) {
print("Deleting existing zip file: ${zipFile.path}");
zipFile.deleteSync();
}
return zipFile;
}
List<File> _createTestFiles(Directory storeDir) {
if (storeDir.existsSync()) {
storeDir.deleteSync(recursive: true);
}
storeDir.createSync();
final files = <File>[];
for (final fileName in _dataFiles.keys) {
final file = File("${storeDir.path}/$fileName");
file.createSync(recursive: true);
print("Writing file: ${file.path}");
file.writeAsStringSync(_dataFiles[fileName]!);
files.add(file);
}
// verify created files
_verifyFiles(storeDir);
return files;
}
void _verifyFiles(Directory filesDir) {
print("Verifying files at: ${filesDir.path}");
final extractedItems = filesDir.listSync(recursive: true);
for (final item in extractedItems) {
print("extractedItem: ${item.path}");
}
print("File count: ${extractedItems.length}");
assert(extractedItems.whereType<File>().length == _dataFiles.length,
"Invalid number of files");
for (final fileName in _dataFiles.keys) {
final file = File('${filesDir.path}/$fileName');
print("Verifying file: ${file.path}");
assert(file.existsSync(), "File not found: ${file.path}");
final content = file.readAsStringSync();
assert(content == _dataFiles[fileName],
"Invalid file content: ${file.path}");
}
print("All files ok");
}
}