Flutter从Google Drive下载SQLite数据库时遇加密/非数据库错误求助
解决Flutter中Google Drive下载SQLite数据库后提示“不是数据库或已加密”的问题
问题根源
直接使用Google Drive公开共享链接下载时,返回的是网页预览内容而非实际数据库文件,导致替换后的文件无法被SQLite识别,触发file is encrypted or is not a database错误。
解决方案
1. 修正Google Drive直接下载链接
Google Drive的普通共享链接是预览页面地址,需要转换为直接下载链接:将原链接中的/file/d/[文件ID]/结构替换为/uc?export=download&id=[文件ID]。
你的链接修改后应为:
String databaseUrl='https://drive.google.com/uc?export=download&id=1Qt4xigUU3d7tO-sdyZVZyQKei9l6AvBz';
2. 增加文件有效性校验
下载完成后,先验证文件是否为合法的SQLite数据库(通过检查文件头特征),避免无效文件覆盖原数据库:
bool isValidSqliteFile(File file) { try { final header = file.readAsBytesSync().sublist(0, 16); return String.fromCharCodes(header) == 'SQLite format 3'; } catch (_) { return false; } }
3. 优化数据库替换流程
先下载到临时文件,验证通过后再替换原数据库,防止替换失败导致原数据库损坏。
修改后的完整代码
import 'dart:io'; import 'dart:typed_data'; import 'package:http/http.dart' as http; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; Future<void> checkAndReplaceDatabase() async { // 修正为Google Drive直接下载链接 String databaseUrl='https://drive.google.com/uc?export=download&id=1Qt4xigUU3d7tO-sdyZVZyQKei9l6AvBz'; final int expectedVersion = 2; String databasesPath = await getDatabasesPath(); String path = join(databasesPath, 'contacts.db'); String tempPath = join(databasesPath, 'temp_contacts.db'); Database? database; try { // 尝试打开现有数据库 database = await openDatabase(path); int currentVersion = await database.getVersion(); if (currentVersion < expectedVersion) { await database.close(); var response = await http.get(Uri.parse(databaseUrl)); if (response.statusCode == 200) { // 先写入临时文件 File tempFile = File(tempPath); await tempFile.writeAsBytes(response.bodyBytes); // 验证临时文件是否为合法SQLite数据库 if (isValidSqliteFile(tempFile)) { // 删除原数据库,替换为临时文件 await File(path).delete(); await tempFile.rename(path); // 打开新数据库并设置版本 Database newDatabase = await openDatabase(path); await newDatabase.setVersion(expectedVersion); await newDatabase.close(); print('Database updated to version $expectedVersion.'); } else { print('Downloaded file is not a valid SQLite database.'); await tempFile.delete(); } } else { print('Failed to download the new database. Status code: ${response.statusCode}'); } } else { print('Database is already up to date (version $currentVersion).'); } } catch (e) { print('Error during database check: $e'); if (database != null) { await database.close(); } } } bool isValidSqliteFile(File file) { try { final Uint8List header = file.readAsBytesSync().sublist(0, 16); return String.fromCharCodes(header) == 'SQLite format 3'; } catch (_) { return false; } }
内容的提问来源于stack exchange,提问作者PLAA Hemantha
相关产品推荐
相关产品推荐

