0

I extracted a string of BASE64 images from the database, put it on the screen and kept reporting an error

String _base64 = user.data.avatar;
var image = utf8.encode(_base64);
var encoded1 = base64.encode(image);
var bytes = base64.decode(encoded1);

Image.memory(bytes,height: 70),

I'm getting the following error...

  Failed decoding image. Data is either invalid, or it is encoded using an unsupported format.
  The following _Exception was thrown resolving an image codec:
  Exception: operation failed

If you know please help me,I'm really worried

  • check this: https://stackoverflow.com/questions/46145472/how-to-convert-base64-string-into-image-with-flutter – Harsh Bhikadia Jan 29 '19 at 02:48
  • what is the [magic number](https://en.wikipedia.org/wiki/List_of_file_signatures) of `bytes`? – pskink Jan 29 '19 at 06:45
  • The first comment can't resolve,this is my bytes [100, 97, 116, 97, 58, 105, 109, 97, 103, 101, 47, 106, 112, 101, 103, 59, 98, 97, 115, 101, 54, 52, 44, 47, 57, 106, 47, 52, 65, 65, 81, 83, 107, 90, 74, 82, 103, 65, 66, 65, 81, 65, 65, 65, 81, 65, 66, 65, 65...] – DO.U.KNOW.IVAN Jan 29 '19 at 08:02
  • this is not a binary: convert it to ASCII and you will see it is not a format that is supported by `Image.memory` constructor – pskink Jan 29 '19 at 08:09
  • this is data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCg.. what convert it to ASCII – DO.U.KNOW.IVAN Jan 29 '19 at 08:52
  • yes, this is what is said: it is not a **binary** data - why at all do you use `base64` twice? – pskink Jan 29 '19 at 08:59
  • but this is base64, this is my question how to convert it to image – DO.U.KNOW.IVAN Jan 29 '19 at 09:05
  • ok what do you see if you call `print(_base64`)? – pskink Jan 29 '19 at 09:08
  • the same... data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCg.. – DO.U.KNOW.IVAN Jan 29 '19 at 09:11
  • so you see that it is pointless to call `utf8.encode` then `base64.encode` and finally `base64.decode` ... what you need instead is to decode bytes `/9j/4AAQSkZJRg .....` – pskink Jan 29 '19 at 09:15
  • and if you do that you will get the binary data like: `00000000 ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 |......JFIF......|` which can be passed to `Image.memory` constructor – pskink Jan 29 '19 at 09:19
  • I'm very grateful to you,pskink.You help me solve my problem.Now I can see the image – DO.U.KNOW.IVAN Jan 29 '19 at 09:26
  • good, your welcome – pskink Jan 29 '19 at 09:31

1 Answers1

0

As previously mentioned in the comments, the cause of this issue is that the base64 String downloaded from the database is being encoded to base64 again. Since you've mentioned that the image you've fetched from the database is already encoded to base64, there's no need for var image = utf8.encode(_base64); and var encoded1 = base64.encode(image); in your approach.

Base64 is a String so no need for utf8.encode() and base64.encode(). Your code snippet should look like this.

String _base64 = user.data.avatar;
var bytes = base64.decode(_base64);

Here's a minimal repro to simulate a working sample app that displays image from a base64 String. Clicking the 'Download' button will save the first image displayed from network to the device's internal storage. The app then converts the downloaded image file to bytes, and then encodes the bytes to base64 - to simulate the base64 String fetched from a database. The base64 String is then decoded to bytes to be displayed using Image.memory(bytes);

import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final imageSrc = 'https://picsum.photos/250?image=9';
  var downloadPath = '';
  var downloadProgress = 0.0;
  Uint8List _imageBytesDecoded;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Expanded(
                flex: 5,
                child: Row(children: [
                  // Display image from network
                  Expanded(
                      flex: 1,
                      child: Column(
                        children: [
                          Text('Image from Network'),
                          Image.network(imageSrc),
                        ],
                      )),
                  Expanded(
                    flex: 1,
                    child: Container(
                      child: Column(
                        children: [
                          Text('Image from File storage'),
                          downloadPath == ''
                              // Display a different image while downloadPath is empty
                              // downloadPath will contain an image file path on successful image download
                              ? Icon(Icons.image)
                              : Image.file(File(downloadPath)),
                        ],
                      ),
                    ),
                  ),
                ])),
            Expanded(
              flex: 1,
              child: Row(
                children: [
                  ElevatedButton(
                    // Download displayed image from imageSrc
                    onPressed: () {
                      downloadFile().catchError((onError) {
                        debugPrint('Error downloading: $onError');
                      }).then((imagePath) {
                        debugPrint('Download successful, path: $imagePath');
                        displayDownloadImage(imagePath);
                        // convert downloaded image file to memory and then base64
                        // to simulate the base64 downloaded from the database
                        base64encode(imagePath);
                      });
                    },
                    child: Text('Download'),
                  ),
                  ElevatedButton(
                    // Delete downloaded image
                    onPressed: () {
                      deleteFile().catchError((onError) {
                        debugPrint('Error deleting: $onError');
                      }).then((value) {
                        debugPrint('Delete successful');
                      });
                    },
                    child: Text('Clear'),
                  )
                ],
              ),
            ),
            LinearProgressIndicator(
              value: downloadProgress,
            ),
            Expanded(
                flex: 5,
                child: Column(
                  children: [
                    Text('Image from base64'),
                    Center(
                      child: _imageBytesDecoded != null
                          ? Image.memory(_imageBytesDecoded)
                          // Display a temporary image while _imageBytesDecoded is null
                          : Icon(Icons.image),
                    ),
                  ],
                )),
          ],
        ),
      ),
    );
  }

  displayDownloadImage(String path) {
    setState(() {
      downloadPath = path;
    });
  }

  // Convert downloaded image file to memory and then base64
  // to simulate the base64 downloaded from the database
  base64encode(String imagePath) async {
    var imageBytes = File(imagePath).readAsBytesSync();
    debugPrint('imageBytes: $imageBytes');
    // This simulates the base64 downloaded from the database
    var encodedImage = base64.encode(imageBytes);
    debugPrint('base64: $encodedImage');
    setState(() {
      _imageBytesDecoded = base64.decode(encodedImage);
      debugPrint('imageBytes: $_imageBytesDecoded');
    });
  }

  Future deleteFile() async {
    final dir = await getApplicationDocumentsDirectory();
    var file = File('${dir.path}/image.jpg');
    await file.delete();
    setState(() {
      // Clear downloadPath and _imageBytesDecoded on file deletion
      downloadPath = '';
      _imageBytesDecoded = null;
    });
  }

  Future downloadFile() async {
    Dio dio = Dio();
    var dir = await getApplicationDocumentsDirectory();
    var imageDownloadPath = '${dir.path}/image.jpg';
    await dio.download(imageSrc, imageDownloadPath,
        onReceiveProgress: (received, total) {
      var progress = (received / total) * 100;
      debugPrint('Rec: $received , Total: $total, $progress%');
      setState(() {
        downloadProgress = received.toDouble() / total.toDouble();
      });
    });
    // downloadFile function returns path where image has been downloaded
    return imageDownloadPath;
  }
}

Demo

Omatt
  • 1,142
  • 9
  • 27