Download ZIP, Extract it and Show the images file in List in UI

By | June 7, 2019
Flutter Download Zip and Extract

Flutter Download Zip and Extract


Watch Video Tutorial
 

 


Add Plugins
 
For downloading, Extracting and saving ZIP in the device, we need some plugins. So open your pubspec.yaml file and add the below plugins.
 

dependencies:
  flutter: 
    sdk: flutter

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^0.1.2
  http: "0.11.3+17"
  path_provider: ^0.4.1
  archive: ^2.0.8
  ...

The ‘http‘ package is for downloading the zip file, ‘path_provider‘ is for saving the file inside the device and the ‘archive‘ package is for
extracting the archive.


So Let’s start…

Download the ZIP
 

  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();
  }

   // Initialize the directory to get the Device's Documents directory //
  _initDir() async {
    if (null == _dir) {
      _dir = (await getApplicationDocumentsDirectory()).path;
    }
  }

  // Download the ZIP file using the HTTP library //
  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);
  }


Extract ZIP
 
Here comes the use of archive library.
Now we will write a function that unarchives the downloaded file and then extracts it. After extracting it we will loop through the archive and then save each file in the documents directory.

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;
    });
  }

  // Unarchive and save the file in Documents directory and save the paths in the array
  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);
      }
    }
  }

Show the Extracted Files in a List
 
We will write a function that will return a List with the images extracted.
 

 buildList() {
  return Expanded(
    child: ListView.builder(
      itemCount: _images.length,
      itemBuilder: (BuildContext context, int index) {
        return Image.file(
          File(_images[index]),
          fit: BoxFit.fitWidth,
        );
      },
    ),
  );
}

 
All done. Now you can just call the the _downloadZip() function to download and extract the ZIP file. Once extracted the file paths will be added to the _images array which is the datasource for the ListView. The ListView row returns an Image with the corresponding image in the _images array index.


Complete Code

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(),
          ],
        ),
      ),
    );
  }
}

Watch the youtube tutorial to see everything in action.

Leave a Reply

Your email address will not be published. Required fields are marked *