Create Zip file from bytes files Flutter web

633

I was struck with a similar issue this week and was able to figure out the problem. I am using html download using anchor.click() method.

Download files as zip method takes input as list of file names as String and list of file data as Uint8List.

Try this and let me know if this works for you!

  _downloadFilesAsZIP(context, List<String> filenames, files) {
    var encoder = ZipEncoder();
    var archive = Archive();
    ArchiveFile archiveFiles = ArchiveFile.stream(
      filenames[0].toString(),
      files[0].lengthInBytes,
      files[0],
    );
    print(archiveFiles);
    archive.addFile(archiveFiles);
    var outputStream = OutputStream(
      byteOrder: LITTLE_ENDIAN,
    );
    var bytes = encoder.encode(archive,
        level: Deflate.BEST_COMPRESSION, output: outputStream);
    print(bytes);
    downloadFile("out.zip", bytes);
  }

  downloadFile(String fileName, Uint8List bytes) {

    final blob = html.Blob([bytes]);
    final url = html.Url.createObjectUrlFromBlob(blob);
    final anchor = html.document.createElement('a') as html.AnchorElement
      ..href = url
      ..style.display = 'none'
      ..download = fileName;
    html.document.body.children.add(anchor);

// download
    anchor.click();

// cleanup
    html.document.body.children.remove(anchor);
    html.Url.revokeObjectUrl(url);
  }
Share:
633
user14757651
Author by

user14757651

Updated on December 31, 2022

Comments

  • user14757651
    user14757651 over 1 year

    I use firebase cloud storage to store some files, then, i have to put them in a zip file and download it, i have to do this ONLY on web, and thats the hard part. im doing it like this now:

    FloatingActionButton(
        child: const Icon(Icons.download),
        onPressed: () async {
          List<int>? bytes;
          webarc.ZipEncoder encoder = webarc.ZipEncoder();
          webarc.Archive archive = webarc.Archive();
    
          try {
            List<String> links = await Database.formLinks();
    
            for (String link in links) {
              String fileName = link.substring(link.lastIndexOf('/') + 1);
              http.Response response = await http.get(
                Uri.parse(link),
                headers: headers,
              );
              webarc.ArchiveFile file = webarc.ArchiveFile.stream(
                fileName,
                response.bodyBytes.elementSizeInBytes,
                response.bodyBytes.toList(),
              );
              archive.addFile(file);
            }
            webarc.OutputStream outputStream = webarc.OutputStream(
              byteOrder: webarc.LITTLE_ENDIAN,
            );
            bytes = encoder.encode(
              archive,
              level: webarc.Deflate.BEST_COMPRESSION,
              modified: DateTime.now(),
              output: outputStream,
            );
          } catch (e) {
            print(e);
            Fluttertoast.showToast(
              msg: 'Errore nel download dello zip.',
              toastLength: Toast.LENGTH_LONG,
              gravity: ToastGravity.BOTTOM,
            );
            return;
          }
          if (bytes == null) {
            Fluttertoast.showToast(
              msg: 'Errore nel download dello zip. bytes nulli.',
              toastLength: Toast.LENGTH_LONG,
              gravity: ToastGravity.BOTTOM,
            );
            return;
          }
    
          String zipFileName = 'forms.zip';
    
          await FileSaver.instance.saveFile(
            zipFileName,
            Uint8List.fromList(bytes),
            'zip',
            mimeType: MimeType.ZIP,
          );
    
          Fluttertoast.showToast(
            msg: 'Zip downloadato correttamente.',
            toastLength: Toast.LENGTH_LONG,
            gravity: ToastGravity.BOTTOM,
          );
        },
      ),
    

    its all perfect, except for the fact that i download the zip file, but the zip file is empty.

    I tryied doing this in many different ways, downloading it with html package, anchoring and clicking a div, but now i think that the package doesnt work, how can i do this? Any help will be accepted, thanks.

    P.S. Here is the database.formLinks function:

     static Future<List<Reference>> getCompiledForms() async =>
      (await formsRef.listAll()).items;
    
     static Future<List<String>> formLinks() async {
    final List<Reference> forms = await getCompiledForms();
    final List<String> links = [];
    for (final form in forms) {
      String url = await form.getDownloadURL();
      links.add(url);
    }
    return links;
    

    }
    And those are the packages that i've used in those functions:

    archive: ^3.1.2 (As webarc)

    http: ^0.13.3 (as http)

    file_saver: ^0.0.10

    fluttertoast: ^8.0.7

    cloud_firestore: ^2.3.0