Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to save image data to sqflite database in flutter for persistence

I'm building a Flutter app where I would like to keep the data offline.

I'm capturing an image using the camera or gallery image picker and able to store that image into a File image variable.

File _avatarImg;

void _getImage(BuildContext context, ImageSource source) {
    ImagePicker.pickImage(
      source: source,
      maxWidth: 400.0,
      maxHeight: 400.0,
    ).then((File image) {
      _avatarImg = image;
    });
  }

This works perfectly however my question is, how would I go about storing this image for persistence? Should I store a string link to the local media directory in the phone where the image is located? If so, I would be worried if the image was accidentally deleted by a user. Or do I store the image itself to the database in a BLOB? What is the best practice for this?

like image 780
ZeroNine Avatar asked Sep 04 '18 16:09

ZeroNine


2 Answers

You can convert an image to BASE64 and store image as a string in your database. Check this link and this one

like image 112
Daniil Yakovlev Avatar answered Nov 02 '22 18:11

Daniil Yakovlev


Images and, in general, files, are meant to be stored as BLOB in a SQLite database.

To do so:

  1. We should create a Picture class:
class Picture {
 final int id;
 final String title;
 final Uint8List picture;

 Picture({this.id, this.title, this.picture});

 Picture.fromMap(Map map) {
   id = map[id];
   title = map[title];
   picture = map[picture];
 }

  Map<String, dynamic> toMap() => {
   "id": id,
   "title": title,
   "picture" : picture,
 };
}
  1. We can then create our table accordingly:
await db.execute("CREATE TABLE Picture(id INTEGER PRIMARY KEY, title TEXT, picture BLOB )");
  1. Create a method to save the Picture in the DB:
void savePicture(Picture picture) async {
  var dbClient = await db;
  await dbClient.insert("Picture", picture.toMap());
}
  1. Create a method to get the Pictures from the DB:
Future<List<Picture>> getPictures() async {
    var dbClient = await db;
    List<Map> list = await dbClient.rawQuery('SELECT * FROM Picture');
    List<Picture> pictures = new List();
    for (int i = 0; i < list.length; i++) {
      pictures.add(new Picture(list[i]["id"], list[i]["text"], list[i]["picture"]));
    }
    return pictures;
  }
}
  1. Save a Picture to the DB:
var image = await get(
  "https://images.pexels.com/photos/2047905/pexels-photo-2047905.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940");
var bytes = image.bodyBytes;
Picture picture = Picture(id, title, picture);
savePicture(picture);
  1. Use it when needed, for example:
Image.memory(picture.picture);

NB: While in the example above we used an Image, this concept applies well with any other kinds of files.

Converting a file to base64 and store it as a string works, but it's not the best solution. One issue is an increase of the storage requirements by 33%, that adds up quickly especially when dealing with large files.

like image 20
Stefano Amorelli Avatar answered Nov 02 '22 18:11

Stefano Amorelli