flutter - 如何解决未处理的异常:FormatException:在 Flutter 中下载文件时找不到中央目录记录的结尾?
问题描述
在我的 Flutter 项目中,我想以 zip 格式下载一些文件,然后以编程方式将其解压缩并保存在本地设备中。因此,出于这个原因,我遵循了一些示例,这是代码-
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:archive/archive.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
class DownloadAssetsDemo extends StatefulWidget {
DownloadAssetsDemo() : super();
final String title = "Download & Extract ZIP Demo";
@override
DownloadAssetsDemoState createState() => DownloadAssetsDemoState();
}
class DownloadAssetsDemoState extends State<DownloadAssetsDemo> {
//
bool _downloading;
String _dir;
List<String> _images, _tempImages;
String _zipPath = 'https://coderzheaven.com/youtube_flutter/images.zip';
String _localZipFileName = 'images.zip';
@override
void initState() {
super.initState();
_images = List();
_tempImages = List();
_downloading = false;
_initDir();
}
_initDir() async {
if (null == _dir) {
_dir = (await getApplicationDocumentsDirectory()).path;
}
}
Future<File> _downloadFile(String url, String fileName) async {
var req = await http.Client().get(Uri.parse(url));
var file = File('$_dir/$fileName');
return file.writeAsBytes(req.bodyBytes);
}
Future<void> _downloadZip() async {
setState(() {
_downloading = true;
});
_images.clear();
_tempImages.clear();
var zippedFile = await _downloadFile(_zipPath, _localZipFileName);
await unarchiveAndSave(zippedFile);
setState(() {
_images.addAll(_tempImages);
_downloading = false;
});
}
unarchiveAndSave(var zippedFile) async {
var bytes = zippedFile.readAsBytesSync();
var archive = ZipDecoder().decodeBytes(bytes);
for (var file in archive) {
var fileName = '$_dir/${file.name}';
if (file.isFile) {
var outFile = File(fileName);
//print('File:: ' + outFile.path);
_tempImages.add(outFile.path);
outFile = await outFile.create(recursive: true);
await outFile.writeAsBytes(file.content);
}
}
}
buildList() {
return Expanded(
child: ListView.builder(
itemCount: _images.length,
itemBuilder: (BuildContext context, int index) {
return Image.file(
File(_images[index]),
fit: BoxFit.fitWidth,
);
},
),
);
}
progress() {
return Container(
width: 25,
height: 25,
padding: EdgeInsets.fromLTRB(0.0, 20.0, 10.0, 20.0),
child: CircularProgressIndicator(
strokeWidth: 3.0,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: <Widget>[
_downloading ? progress() : Container(),
IconButton(
icon: Icon(Icons.file_download),
onPressed: () {
_downloadZip();
},
),
],
),
body: Container(
child: Column(
children: <Widget>[
buildList(),
],
),
),
);
}
}
此示例适用于所有功能 - zip 文件下载、解压缩文件和加载图像。
但问题是
当我想从已将 sqlite 数据库(大小:19 mb)保存为 zip 文件的所需位置下载文件时,它不像给定代码那样工作。
它显示以下错误异常-
[错误:flutter/lib/ui/ui_dart_state.cc(186)] 未处理的异常:FormatException:找不到中央目录记录的结尾
而且我不完全了解问题是在我的下载路径中还是我需要在我的编码示例中进行一些更改?
因此,我需要一些建议来修复此异常并从所需的 url 下载并解压缩所需的文件。
解决方案
这可能是由于文件在下载后在尝试提取之前尚未刷新到文件系统。要解决此问题,请将_downloadFile
方法更新为以下
Future<File> _downloadFile(String url, String fileName) async {
var req = await http.Client().get(Uri.parse(url));
var file = File('$_dir/$fileName');
return file.writeAsBytes(req.bodyBytes, flush: true); // Added flush: true
}
来自dart:io
文档
Future<File> writeAsBytes(List<int> bytes, {FileMode mode = FileMode.write, bool flush = false})
Writes a list of bytes to a file.
Opens the file, writes the list of bytes to it, and closes the file. Returns a Future<File> that completes with this [File] object once the entire operation has completed.
By default [writeAsBytes] creates the file for writing and truncates the file if it already exists. In order to append the bytes to an existing file, pass [FileMode.append] as the optional mode parameter.
Note: --> If the argument [flush] is set to true, the data written will be flushed to the file system before the returned future completes.
推荐阅读
- stored-procedures - 在雪花中,如何从动态查询中删除单引号。在这种情况下,反斜杠没有多大用处
- javascript - 将图标传递给 JS 对象
- python - 我的 django web app 评论表单显示不正确
- python - 为 conv1D Keras NN 找到正确的输入和输出形状
- odoo - Odoo 覆盖删除记录确认对话框
- batch-file - 批处理文件从变量中未知数量的分隔符中提取某些标记
- r - 只有字符串可以在 R 中的函数内转换为符号
- node.js - UserId undefined-socket io /node js
- java - lombok @RequiredArgsConstructor 如何将值注入构造函数spring boot
- node.js - 在我的 Electron 应用程序中,我在哪里执行我的首次启动功能?