This is a mixture of FileImage
and NetworkImage
. It will download the image from the url once,
save it locally in the file system, and then use it from there in the future.
In more detail:
Given a file and url of an image, it first tries to read it from the local file. It decodes the
given File
object as an image, associating it with the given scale.
However, if the image doesn't yet exist as a local file, it fetches the given URL from the network, associating it with the given scale, and then saves it to the local file. The image will be cached regardless of cache headers from the server.
Notes:
-
If the provided url is null or empty,
NetworkToFileImage
will default toFileImage
. It will read the image from the local file, and won't try to download it from the network. -
If the provided file is null,
NetworkToFileImage
will default toNetworkImage
. It will download the image from the network, and won't save it locally.
If you also listed path_provider
in your pubspec.yaml file:
path_provider: ^1.4.4
Then you can create a file from a file name:
Future<File> file(String filename) async {
Directory dir = await getApplicationDocumentsDirectory();
String pathName = p.join(dir.path, filename);
return File(pathName);
}
var myFile = await file("myFileName.png"),
Then, create the image:
Image(image:
NetworkToFileImage(
url: "https://example.com/someFile.png",
file: myFile))
If you make debug: true
it prints to the console whether the image was read from the file or
fetched from the network:
Image(image:
NetworkToFileImage(
url: "https://example.com/someFile.png",
file: myFile,
debug: true))
Try running the NetworkToFileImage example.
The directory where you want to save the image must already exist in the local disk. Otherwise, the image won't be saved.
You can also load images to use with the Canvas
object of the paint
method of a CustomPainter
.
ImageProviders can't be used directly with the Canvas
object, but you can use the
provided ImageForCanvas
class.
For example: Suppose a User
object that contains url
and filename
properties:
var imageForCanvas = ImageForCanvas<User>(
imageProviderSupplier: (User user) => NetworkToFileImage(file: user.file, url: user.url),
keySupplier: (User user) => user.filename,
loadCallback: (image, obj, key) => setState((){}),
);
// While the image is downloading, this will return null.
var myImage = imageForCanvas.image(user);
if (myImage != null) {
canvas.drawImage(myImage, ...);
}
It will use the regular image cache from Flutter, and works not only with NetworkToFileImage
provider, but any other image providers.
Try running the ImageForCanvas example.
You can set mock files (local and in the network). Please see methods:
setMockFile(File file, Uint8List bytes)
setMockUrl(String url, Uint8List bytes)
clearMocks()
clearMockFiles()
clearMockUrls()
Your mocked urls are usually only seen by the NetworkToFileImage
class. However, you may override
the default Dart http methods so that these urls are visible to other ImageProviders.
To that end, simply call this method:
NetworkToFileImage.startHttpOverride();
You can stop the http override by calling:
NetworkToFileImage.stopHttpOverride();
- flutter_image
- image_downloader
- flutter_advanced_networkimage
- extended_image
- cached_network_image:
Note
cached_network_image
will cache an image for some time, and then evict the image from the cache when the cache gets full, or according to other conditions. Meanwhile,network_to_file_image
will simply download the image and leave it there. Think WhatsApp or Telegram: someone sends you an image, it's downloaded and kept there
in your Gallery/files forever, or until someone deletes it manually. Also,network_to_file_image
is much lighter thancached_network_image
, which uses SQLite under the hood.
Special Thanks: Hugo Passos helped me with the http override.
The Flutter packages I've authored:
- async_redux
- fast_immutable_collections
- provider_for_redux
- i18n_extension
- align_positioned
- network_to_file_image
- image_pixels
- matrix4_transform
- back_button_interceptor
- indexed_list_view
- animated_size_and_fade
- assorted_layout_widgets
- weak_map
- themed
My Medium Articles:
- Async Redux: Flutter’s non-boilerplate version of Redux ( versions: Português)
- i18n_extension ( versions: Português)
- Flutter: The Advanced Layout Rule Even Beginners Must Know ( versions: русский)
- The New Way to create Themes in your Flutter App
My article in the official Flutter documentation:
---
Marcelo Glasberg:
https://github.com/marcglasberg
https://twitter.com/glasbergmarcelo
https://stackoverflow.com/users/3411681/marcg
https://medium.com/@marcglasberg