Flutter压缩解压插件flutter_minizip_ffi_bindings的使用

Flutter压缩解压插件flutter_minizip_ffi_bindings的使用

flutter_minizip_ffi_bindings 是一个用于在 Flutter 中进行文件压缩和解压的插件。它通过 FFI(Foreign Function Interface)绑定到 zlib-ng/minizip-ng 库,从而允许你在 Dart 代码中调用 C 函数。

注意事项

这个包不包含 minizip 的二进制库。你需要自行构建 libminizip 并将其添加到你的应用项目或示例项目中。

在 Android 上运行示例

  1. 构建你的 Android libminizip
  2. 将构建好的 libminizip.so 文件复制到以下路径:
    example/android/app/src/main/jniLibs/
    ├── arm64-v8a
    │   └── libminizip.so
    ├── armeabi-v7a
    │   └── libminizip.so
    ├── x86
    │   └── libminizip.so
    └── x86_64
        └── libminizip.so
    
  3. 执行以下命令运行示例:
    cd example && flutter run
    

在 iOS 上运行示例

  1. 构建你的 iOS libminizip
  2. 将构建好的 libminizip.3.0.dylibinclude/ 目录复制到以下路径:
    example/ios/Runner/minizip/
    ├── include
    │   ├── mz.h
    │   ...
    │   └── mz_zip_rw.h
    └── libminizip.3.0.dylib
    
  3. 执行以下命令运行示例:
    cd example && flutter run
    

在你的应用项目中使用此插件

  1. pubspec.yaml 文件中将此包作为开发依赖项添加:
    dev_dependencies:
      flutter_minizip_ffi_bindings: ^x.y.z
    
  2. 构建你的 libminizip 并将其添加到你的应用的原生项目中。
  3. 导入插件:
    import 'package:flutter_minizip_ffi_bindings/flutter_minizip_ffi_bindings.dart';
    

完整示例代码

以下是完整的示例代码,展示了如何使用 flutter_minizip_ffi_bindings 插件来列出和读取 ZIP 文件中的文件。

import 'dart:convert';
import 'dart:ffi' as ffi;
import 'dart:io';

import 'package:ffi/ffi.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:flutter_minizip_ffi_bindings/flutter_minizip_ffi_bindings.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';

const _sampleDataName = 'minizip-ng-master.zip';

Future<void> _copySampleData() async {
  final sampleData = await rootBundle.load('assets/$_sampleDataName');
  final filesDir = await getApplicationSupportDirectory();
  final dstPath = p.join(filesDir.path, _sampleDataName);
  final dst = File(dstPath);
  await dst.writeAsBytes(sampleData.buffer.asUint8List());
}

final _minizip = () {
  final lib = Platform.isIOS
      ? ffi.DynamicLibrary.process()
      : ffi.DynamicLibrary.open('libminizip.so');
  return Minizip(lib);
}();

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await _copySampleData();
  runApp(const _App());
}

[@immutable](/user/immutable)
class _App extends StatelessWidget {
  const _App({
    Key? key,
  }) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('flutter_minizip_ffi_bindings_example'),
        ),
        body: const _Body(),
      ),
    );
  }
}

[@immutable](/user/immutable)
class _Body extends StatefulWidget {
  const _Body({
    Key? key,
  }) : super(key: key);

  [@override](/user/override)
  _BodyState createState() => _BodyState();
}

class _BodyState extends State<_Body> {
  List<String>? _paths;

  Future<void> _listFilesInZip() async {
    final filesDir = await getApplicationSupportDirectory();
    final path = p.join(filesDir.path, _sampleDataName);

    final handle = calloc<ffi.Pointer<ffi.Void>>();
    _minizip.mz_zip_reader_create(handle);
    _minizip.mz_zip_reader_open_file(handle.value, path.toNativeUtf8().cast());

    final paths = <String>[];
    _minizip.mz_zip_reader_goto_first_entry(handle.value);
    do {
      if (_minizip.mz_zip_reader_entry_is_dir(handle.value) == MZ_OK) {
        continue;
      }

      final info = calloc<ffi.Pointer<mz_zip_file_s>>();
      _minizip.mz_zip_reader_entry_get_info(handle.value, info);
      paths.add(info.value.ref.filename.cast<Utf8>().toDartString());
    } while (_minizip.mz_zip_reader_goto_next_entry(handle.value) == MZ_OK);

    _minizip.mz_zip_reader_close(handle.value);
    _minizip.mz_zip_reader_delete(handle);

    setState(() => _paths = paths);
  }

  [@override](/user/override)
  void initState() {
    super.initState();
    _listFilesInZip();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    final _paths = this._paths;
    if (_paths == null) {
      return const Center(
        child: CircularProgressIndicator(),
      );
    }

    return Scrollbar(
      child: ListView.builder(
        itemCount: _paths.length,
        itemBuilder: (context, index) {
          return _ListTile(path: _paths[index]);
        },
      ),
    );
  }
}

[@immutable](/user/immutable)
class _ListTile extends StatelessWidget {
  const _ListTile({
    required this.path,
    Key? key,
  }) : super(key: key);

  final String path;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return DecoratedBox(
      decoration: BoxDecoration(
        border: Border(
          bottom: BorderSide(
            color: Theme.of(context).dividerColor,
          ),
        ),
      ),
      child: ListTile(
        title: Text(path),
        onTap: () {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) {
                return _Detail(path: path);
              },
            ),
          );
        },
      ),
    );
  }
}

[@immutable](/user/immutable)
class _Detail extends StatelessWidget {
  const _Detail({
    required this.path,
    Key? key,
  }) : super(key: key);

  final String path;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(path),
      ),
      body: _Content(path: path),
    );
  }
}

[@immutable](/user/immutable)
class _Content extends StatelessWidget {
  const _Content({
    required this.path,
    Key? key,
  }) : super(key: key);

  final String path;

  Future<List<String>> _readFileInZip(String filePath) async {
    final filesDir = await getApplicationSupportDirectory();
    final path = p.join(filesDir.path, _sampleDataName);

    final handle = calloc<ffi.Pointer<ffi.Void>>();
    _minizip.mz_zip_reader_create(handle);
    _minizip.mz_zip_reader_open_file(handle.value, path.toNativeUtf8().cast());

    _minizip.mz_zip_reader_locate_entry(
      handle.value,
      filePath.toNativeUtf8().cast(),
      0,
    );

    final info = calloc<ffi.Pointer<mz_zip_file_s>>();
    _minizip.mz_zip_reader_entry_get_info(handle.value, info);

    final len = info.value.ref.uncompressed_size;
    final buf = calloc<ffi.Uint8>(len);

    _minizip.mz_zip_reader_entry_open(handle.value);
    _minizip.mz_zip_reader_entry_read(handle.value, buf.cast(), len);

    final bytes = List<int>.from(buf.asTypedList(len));

    _minizip.mz_zip_reader_entry_close(handle.value);
    _minizip.mz_zip_reader_close(handle.value);
    _minizip.mz_zip_reader_delete(handle);

    final lines = () {
      try {
        return const Utf8Decoder().convert(bytes);
      } catch (e) {
        return 'Error: Invalid UTF-8 Strings';
      }
    }();

    return const LineSplitter().convert(lines);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FutureBuilder<List<String>>(
      future: _readFileInZip(path),
      builder: (context, snapshot) {
        final lines = snapshot.data;
        if (snapshot.connectionState != ConnectionState.done || lines == null) {
          return const Center(
            child: CircularProgressIndicator(),
          );
        }

        return Scrollbar(
          child: SafeArea(
            child: ListView.builder(
              padding: const EdgeInsets.all(8),
              itemCount: lines.length,
              itemBuilder: (context, index) {
                return Text(lines[index]);
              },
            ),
          ),
        );
      },
    );
  }
}

更多关于Flutter压缩解压插件flutter_minizip_ffi_bindings的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter压缩解压插件flutter_minizip_ffi_bindings的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


flutter_minizip_ffi_bindings 是一个 Flutter 插件,用于在 Flutter 应用中压缩和解压缩文件。它基于 minizip 库,并通过 FFI (Foreign Function Interface) 在 Flutter 中调用原生代码。

以下是如何在 Flutter 项目中使用 flutter_minizip_ffi_bindings 插件的基本步骤:

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 flutter_minizip_ffi_bindings 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_minizip_ffi_bindings: ^1.0.0  # 请检查最新版本

然后运行 flutter pub get 以获取依赖。

2. 导入插件

在需要使用压缩或解压缩功能的 Dart 文件中导入插件:

import 'package:flutter_minizip_ffi_bindings/flutter_minizip_ffi_bindings.dart';

3. 压缩文件

使用 MinizipFFI.compressFiles 方法可以将多个文件压缩到一个 ZIP 文件中:

void compressFiles() async {
  List<String> filesToCompress = [
    '/path/to/file1.txt',
    '/path/to/file2.txt',
  ];
  String outputZipPath = '/path/to/output.zip';

  try {
    await MinizipFFI.compressFiles(filesToCompress, outputZipPath);
    print('文件压缩成功: $outputZipPath');
  } catch (e) {
    print('文件压缩失败: $e');
  }
}

4. 解压缩文件

使用 MinizipFFI.extractFiles 方法可以将 ZIP 文件解压缩到指定目录:

void extractFiles() async {
  String zipFilePath = '/path/to/input.zip';
  String outputDirectory = '/path/to/output/directory';

  try {
    await MinizipFFI.extractFiles(zipFilePath, outputDirectory);
    print('文件解压缩成功: $outputDirectory');
  } catch (e) {
    print('文件解压缩失败: $e');
  }
}
回到顶部