微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何解决未处理的异常:FormatException:在 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 文件的所需位置下载文件时,它不像给定代码那样工作。

显示以下错误异常-

[ERROR: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.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。