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 = 'http://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 = 'http://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.