Search code examples
downloadbase64blobencodeflutter-web

How to encode and download png on Flutter web


I am trying to take a screenshot of a widget and save it as a png.

Its working fine for macos and ios but not for desktop(chrome).

The file downloaded from browser seems to be not encoded correct, I have tried a lot of different encodings but cant get it working.

Would be nice if someone knows how to encode the image so its downloaded correct in web too.

    final boundary = _boundaryKey.currentContext.findRenderObject() as RenderRepaintBoundary;
    final image = await boundary.toImage(pixelRatio: 2);
    final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    final pngBytes = byteData.buffer.asUint8List();

    if (kIsWeb) {
        final blob = html.Blob(<dynamic>[base64Encode(pngBytes)], 'image/png');
        final anchorElement = html.AnchorElement(
          href: html.Url.createObjectUrlFromBlob(blob),
        )
          ..setAttribute('download', 'details.png')
          ..click();
    } else {
        await File('details_${widget.order.id}'.trim().replaceAll(' ', '_')).writeAsBytes(pngBytes);
    }

Solution

  • The trick is to set 'application/octet-stream' when creating the Blob

    final fileName = 'details_${widget.order.id.trim().replaceAll(' ', '_')}';
    final boundary = _boundaryKey.currentContext.findRenderObject() as RenderRepaintBoundary;
    final image = await boundary.toImage(pixelRatio: 2);
    final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    final pngBytes = byteData.buffer.asUint8List();
    final blob = html.Blob(<dynamic>[pngBytes], 'application/octet-stream');
    html.AnchorElement(href: html.Url.createObjectUrlFromBlob(blob))
        ..setAttribute('download', fileName)
        ..click();