How to save images from assets to the internal storage in flutter?

Viewed 7314

I am trying to save the image from assets to internal storage. But, I could not load the image from assets to file. Here is what I have done:

onTap: () async {
  
  final String documentPath = (await getApplicationDocumentsDirectory()).path;
  String imgPath = (galleryItems[currentIndex].assetName).substring(7);
  File image = await getImageFileFromAssets(imgPath);

  print(image.path);
}

I used substring(7) to eliminate assets/ as, my assetName comes as assets/images/foo.jpg.

Future<File> getImageFileFromAssets(String path) async {
  final byteData = await rootBundle.load('assets/$path');

  final file =
      await File('${(await getApplicationDocumentsDirectory()).path}/$path')
          .create(recursive: true);
  await file.writeAsBytes(byteData.buffer
      .asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));

  return file;
}

After I get image, I don't know how to proceed forward to create a directory with my name in internal storage. And, copy file there.

*Note:- I have editted the post, as some basic mistakes were pointed out.

Update

Here is what I came up with. And it saves image in the /storage/emulated/0/Android/data/com.example.my_project/files/Pics/foo.jpg path.

File image = await getImageFileFromAssets(imgPath);

final extDir = await getExternalStorageDirectory();

// Path of file
final myImagePath = '${extDir.path}/Pics';

// Create directory inside where file will be saved
await new Directory(myImagePath).create();

// File copied to ext directory.
File newImage =
    await image.copy("$myImagePath/${basename(imgPath)}");

print(newImage.path);

Here are some links that really helped me:

Special thanks to @David for the help. Please see comments to understand full scene if you are here to solve your similar problem.

So, I am accepting the answer from @David.

2 Answers

You are trying to create a file object in a path that doesn't exist. You're using your asset path, the path relative to the root of your Flutter project. However, this path doesn't exist in the device's documents folder, so the file can't be created there. The file also doesn't exist in the assets folder because you're prepending the documents path.

To fix your issue, you should pass assetName to rootBundle.load(), without the documents path and open the File() somewhere like $documentPath/foo.jpg

Edit: To create the file you still have to call File.create, so you need to run:

final file = await File('$documentPath/images/foo.jpg').create(recursive: true);

For future reference, this is just to update the solution of @Biplove which really helped me a lot as a newbie...

Future<File> getImageFileFromAssets(String unique, String filename) async {
  ByteData byteData = await rootBundle.load(assets/filename));

  // this creates the file image
  File file = await File('$imagesAppDirectory/$filename').create(recursive: true); 

  // copies data byte by byte
  await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
  
  return file;
}

Thanks.

Related