如何为含SQLite数据库的Flutter桌面项目生成带库的EXE文件?
Flutter Windows打包自带SQLite数据库解决方案
核心思路
Flutter桌面应用的资源目录是只读的,直接打包.db文件无法在运行时修改,所以需要两步:打包时将数据库纳入资源,首次启动时复制到可读写目录。
1. 配置数据库资源
- 在项目根目录新建
assets文件夹,把你的.db文件放进去(比如assets/app_db.db) - 修改
pubspec.yaml,添加资源声明:
执行flutter: assets: - assets/app_db.dbflutter pub get生效,这样打包时数据库会被自动包含到应用资源中。
2. 运行时复制数据库到可读写路径
依赖path_provider获取系统可读写目录,使用sqflite_common_ffi作为桌面端SQLite实现:
- 先添加依赖到
pubspec.yaml:dependencies: path_provider: ^2.1.0 sqflite_common_ffi: ^2.2.0 - 编写初始化逻辑:
import 'dart:io'; import 'dart:typed_data'; import 'package:flutter/services.dart'; import 'package:path_provider/path_provider.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; Future<Database> initLocalDb() async { // 初始化桌面端SQLite sqfliteFfiInit(); databaseFactory = databaseFactoryFfi; // 获取应用专属可读写目录(Windows下为AppData/Roaming/你的应用名) final appDocDir = await getApplicationDocumentsDirectory(); final dbSavePath = '${appDocDir.path}/app_db.db'; final dbFile = File(dbSavePath); // 仅当数据库不存在时从assets复制 if (!await dbFile.exists()) { final ByteData dbAsset = await rootBundle.load('assets/app_db.db'); final Uint8List dbBytes = dbAsset.buffer.asUint8List( dbAsset.offsetInBytes, dbAsset.lengthInBytes, ); await dbFile.writeAsBytes(dbBytes); } // 打开数据库,后续CURD操作直接使用这个实例 return await openDatabase(dbSavePath); } - 在应用启动时初始化:
void main() async { WidgetsFlutterBinding.ensureInitialized(); // 初始化数据库 await initLocalDb(); runApp(const MyApp()); }
3. 验证打包效果
执行flutter build windows后,检查build/windows/runner/Release/data/flutter_assets/assets目录,确认.db文件存在。运行EXE后,可手动前往C:\Users\你的用户名\AppData\Roaming\你的应用名目录,查看数据库是否被成功复制。
常见问题排查
- 数据库复制失败:检查
pubspec.yaml中assets路径和代码中加载路径是否完全一致,注意文件名大小写(Windows不区分,但代码需匹配) - CURD报错:确认使用
sqflite_common_ffi而非移动端的sqflite,两者API兼容但桌面端必须用前者 - 日志调试:可在复制逻辑中添加
print(dbSavePath),直接输出路径后手动验证文件是否存在
内容的提问来源于stack exchange,提问作者Atiprad Mishra
相关产品推荐
相关产品推荐

