73

What I want to do is load an image in a Material Widget to use it in a ListTile, but this asset might not exist.

class MyImage extends StatelessWidget {
  final imagePath;

  MyIcon(String iconName) {
    try { // check if imagePath exists. Here is the problem
      imagePath = check('assets/$iconName.png/');
    } catch (e, s) { // if not
      imagePath = 'assets/$iconName.png/';
    }
  }

 @override
  Widget build(BuildContext context) {
    return Material(...here I will load the imagePath...);
 }
}

So, since I'm using a Stateless widget, I have to know beforehand if the image exists, otherwise I'll load a null right?

Zoe
  • 27,060
  • 21
  • 118
  • 148
Isaac
  • 1,436
  • 2
  • 15
  • 29

4 Answers4

102

In order to see whether or not a file exists in internal local storage of the app use:

import 'dart:io' as io;
var syncPath = await path;

// for a file
await io.File(syncPath).exists();
io.File(syncPath).existsSync();

// for a directory
await io.Directory(syncPath).exists();
io.Directory(syncPath).existsSync();
Sisir
  • 4,584
  • 4
  • 26
  • 37
Nae
  • 14,209
  • 7
  • 52
  • 79
40

For me simply worked this:

import 'dart:io';
File("path/to/file").exists() 

or, for checking it synchronously

import 'dart:io';
File("path/to/file").existsSync()
Giuse Petroso
  • 557
  • 6
  • 7
  • 2
    `await File("path/to/file").exists()` is the same as `File("path/to/file").existsSync()` right? Why do they both exist? – Joran Dec 12 '20 at 12:56
  • 3
    @Joran I think they exists because you may be in a closure which isn't marked with async keyword but you want to wait for the result. I think it's on purpose. – Giuse Petroso Jan 07 '21 at 17:43
17

Looks like you want to try to load an ImageProvider from a folder where the image may or may not exist and then, if it does not, load a fallback asset image (which you can be sure will exist as you'll put it in your root bundle).

Try this:

ImageProvider getImageProvider(File f) {
  return f.existsSync()
      ? FileImage(f)
      : const AssetImage('images/fallback.png');
}
Richard Heap
  • 48,344
  • 9
  • 130
  • 112
  • 1
    Thanks! That's what I was looking for, but for some reason `f.existsSync()` always returns `false`. – Isaac Oct 04 '18 at 09:37
  • 3
    Ok, I think that this does not work. `f.existsSync` is always going to be false because assets are not files. They are bundles within the executable, according to a comment from this new question I asked https://stackoverflow.com/questions/52653032/flutter-file-existssync-always-returns-false – Isaac Oct 05 '18 at 12:39
  • As I said before, you don't need to test whether assets exist - you know that at build time. But in the comment you say "which I'll previously download (semi-automatically)", so these you will have written to a read/write folder and can test whether they exist. – Richard Heap Oct 05 '18 at 13:27
  • I don't understand. These files are written to the assets folder, the assets folder is mentioned in the pubspec, then the app is compiled. Then I need to test whenever the user want to see some info from this team, if its icon exists because it's not sure that every team has its icon. – Isaac Oct 05 '18 at 15:29
  • 1
    So, what you really want to know is whether an asset exists. The best way to do this is to include an additional (text? json?) asset that is a list of all the other assets. In fact, flutter creates one for you. It's called `AssetManifest.json`. It's an implementation detail, so may change, but seems to work for now. – Richard Heap Oct 05 '18 at 15:37
  • Great! I'll take a look at that – Isaac Oct 05 '18 at 15:48
-3

In order to see whether or not a file exists in local storage (as with image.network) now you can use :

Image.file(File("path/to/file"),
errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) {return Text('file access error');
MaB
  • 25
  • 1
  • 4