33

Is there a way to use an asset image as a File. I need a File so it can be used for testing it over the internet using http. I've tried some answers from Stackoverflow.com (How to load images with image.file) but get an error 'Cannot open file, (OS Error: No such file or directory, errno = 2)'. The attached code line also gives an error.

File f = File('images/myImage.jpg');

RaisedButton(
   onPressed: ()=> showDialog(
     context: context,
     builder: (_) => Container(child: Image.file(f),)),
   child: Text('Show Image'),)

Using Image.memory widget(works)

Future<Null> myGetByte() async {
    _byteData = await rootBundle.load('images/myImage.jpg');
  }

  /// called inside build function
  Future<File> fileByte = myGetByte();

 /// Show Image
 Container(child: fileByte != null
 ? Image.memory(_byteData.buffer.asUint8List(_byteData.offsetInBytes, _ 
 byteData.lengthInBytes))
 : Text('No Image File'))),
Ant D
  • 2,481
  • 6
  • 18
  • 34

3 Answers3

59

You can access the byte data via rootBundle. Then, you can save it to the device's temporary directory which is obtained by path_provider (you need to add it as a dependency).

import 'dart:async';
import 'dart:io';

import 'package:flutter/services.dart' show rootBundle;
import 'package:path_provider/path_provider.dart';

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

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

  return file;
}

In your example, you would call this function like this:

File f = await getImageFileFromAssets('images/myImage.jpg');

For more information on writing the byte data, check out this answer.

You will need to await the Future and in order to do that, make the function async:

RaisedButton(
   onPressed: () async => showDialog(
     context: context,
     builder: (_) => Container(child: Image.file(await getImageFileFromAssets('images/myImage.jpg')))),
   child: Text('Show Image'));
creativecreatorormaybenot
  • 114,516
  • 58
  • 291
  • 402
  • I tested it and got an error: 'The argument type Future can't be assigned to the parameter type File'. I've added test code above. – Ant D Mar 22 '19 at 08:59
  • @AntD It is working correctly. You need to `await` the `Future` because it is an asynchronous request. To understand how `Future`'s work in Dart, you can read this guide: https://www.dartlang.org/tutorials/language/futures – creativecreatorormaybenot Mar 22 '19 at 13:06
  • Thank you, but File f = await getImageFileFromAssets('images/myImage.jpg'); Gives 2 errors, unexpected text 'await' and Future file cannot be assigned to file. I'm using Android Studio, don't know how I'm getting the errors. – Ant D Mar 22 '19 at 13:29
  • @AntD You should really check out the article I linked. I edited my answer to include the code you added. – creativecreatorormaybenot Mar 22 '19 at 13:34
  • @ creativecreatorormaybenot thank you very much, now it works after some experimenting, pasting the working code along above and thanks also to @ Günter Zöchbauer for mentioning to write to memory. Don't know about its efficiency of what I've done, if any thing to be cautious about please mention. – Ant D Mar 22 '19 at 17:22
  • @ creativecreatorormaybenot thought I had the answer. But no, I can display File image from memory but I don't have a File for Image.File. Still trying to get it to work. – Ant D Mar 23 '19 at 14:30
  • 4
    @ creativecreatorormaybenot now it really works. The problem I had was the function 'getImageFileFromAssets' was adding to it 'images/myImage.jpg' at getTemporaryDirectory(), instead of only '/myImage.jpg'. Finally I have a File! Thanks. – Ant D Mar 23 '19 at 17:41
  • 7
    Hi, I follow the solution but I get the error about Unhandled Exception: FileSystemException: Cannot open file, path = '/data/user/0/com.example.myApp/cache/images/black.png' (OS Error: No such file or directory, errno = 2) – dipgirl Mar 25 '20 at 08:20
  • 6
    @creativecreatorormaybenot I think you should replace `final file = File('${(await getTemporaryDirectory()).path}/$path');` with `final file = File('${(await getTemporaryDirectory()).path}/image.png');` it will save time for future commers – nimi0112 Apr 23 '20 at 18:29
  • 14
    I added `await file.create(recursive: true);` after creating the file. Because if your path includes directories that does not exist yet, writing to that file fails because by default create is with recursive false. – Mustafa Berkay Mutlu Aug 02 '20 at 18:50
  • @MustafaBerkayMutlu Thanks for pointing out it. You've saved my day! – Hoon Aug 06 '20 at 21:23
  • getTemporaryDirectory() this function is not working now when I am using... – palak Jan 20 '21 at 05:15
  • 1
    creativecreatorormaybenot, can you please edit your answer to include the line from @MustafaBerkayMutlu ? – serendipity Feb 27 '22 at 10:25
  • 1
    To solve the `FileSystemException: Cannot open file, path = '/data/user/0...` error, just use this method instead: ```Future getImageFileFromAssets(String path) async { final byteData = await rootBundle.load('assets/$path'); final file = await File('${(await getTemporaryDirectory()).path}/$path') .create(recursive: true); await file.writeAsBytes(byteData.buffer .asUint8List(byteData.offsetInBytes, byteData.lengthInBytes)); return file; }``` – gogobebe2 Aug 30 '22 at 07:43
4

Get File from Asset without providing a path.

import 'package:path_provider/path_provider.dart';


Future<File> getImageFileFromAssets(Asset asset) async {
    final byteData = await asset.getByteData();

    final tempFile =
        File("${(await getTemporaryDirectory()).path}/${asset.name}");
    final file = await tempFile.writeAsBytes(
      byteData.buffer
          .asUint8List(byteData.offsetInBytes, byteData.lengthInBytes),
    );

    return file;
  }
Prince
  • 245
  • 4
  • 9
  • Thanks a lot man, you asked me alongside the next [link](https://github.com/flutter/flutter/issues/65995#issuecomment-755071269). For people with problems with the image_picker in iOS 14.x – Andres Paladines Jan 06 '21 at 04:35
  • 3
    Asset class does not exist anywhere that I can find. Any insights? – Luke Pighetti Feb 22 '21 at 15:46
3

Make use of flutter_absolute_path package.

flutter_absolute_path: ^1.0.6

In pubsec.yaml

To convert file path from this format :

“content://media/external/images/media/5275”

To

"/storage/emulated/0/DCIM/Camera/IMG_00124.jpg”

======

List <File> fileImageArray = [];
assetArray.forEach((imageAsset) async {
final filePath = await FlutterAbsolutePath.getAbsolutePath(imageAsset.identifier);

File tempFile = File(filePath);
if (tempFile.existsSync()) {
    fileImageArray.add(tempFile);
}
Martin
  • 2,411
  • 11
  • 28
  • 30
Mohd Danish Khan
  • 1,044
  • 11
  • 12