How to save images from assets to the internal storage in flutter?
Solution 1
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);
Solution 2
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.
Biplove Lamichhane
Hello!!! Thank you for visiting my profile. If I am of any help to you, it's my pleasure.
Updated on December 23, 2022Comments
-
Biplove Lamichhane over 1 year
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 eliminateassets/
as, my assetName comes asassets/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:
- Flutter How to save Image file to new folder in gallery?
- How to Save Image File in Flutter ? File selected using Image_picker plugin
- How to convert asset image to File?
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.
-
Yadu over 3 yearsnow the error must have changed? please post it
-
Biplove Lamichhane over 3 yearsNo, now there is not any error. What error are you expecting??? It throws exception
FileSystemException: Cannot open file, path = '/data/user/0/com.example.pig_salang/app_flutter/images/foo.jpg' (OS Error: No such file or directory, errno = 2)
if I remove.create(recursive: true)
. -
Yadu over 3 yearsso you need to write the file to a folder in the root storage which is available to anyone using the device? or you just need a safe place on the device's internal storage?
-
Biplove Lamichhane over 3 yearsIn the root storage... So, that user could get the files from assets to there gallery.
.create()
removed. -
David over 3 yearsI'm no longer clear what the problem is, but if you want the file to be accessible by the user, you should use
getExternalStorageDirectory
-
Biplove Lamichhane over 3 yearsI ll look on that
-
Biplove Lamichhane over 3 yearsThen, I get exception of
FileSystemException: Cannot open file, path = '/data/user/0/com.example.pig_salang/app_flutter/images/foo.jpg' (OS Error: No such file or directory, errno = 2)
-
David over 3 yearsYes, that's because you added the
images
folder. I meant specifically justfoo.jpg
, otherwise you have to create the directory as explained in the docs: api.flutter.dev/flutter/dart-io/Directory-class.html -
David over 3 yearsSorry, my mistake, forgot to actually create the file. Then you can just use the
recursive
property, instead of creating the directory in a separate step. I've edited my answer. -
Biplove Lamichhane over 3 yearsOkay... I ll look at it.
-
Yadu over 3 yearswhy are you giving it a external directory? do
rootBundle.load('assets/somefolder/somefile.png')
as you are accessing a assets bundled with your app you have to look for it in assets root -
Biplove Lamichhane over 3 yearsPlease review post, as I made changes.
-
w461 over 2 yearsIs there a drawback using
image.copy
or why do you chose using a byte by byte copy instead? -
damiro over 2 yearsat that time, this is the best solution I could find. The situation is that I need to copy an Image from assets to App directory without displaying it. To answer your question, I don't think there will be draw backs if you can make if work by the use of
image.copy
.