This is a mixture of FileImage and NetworkImage.

Overview

pub package

network_to_file_image

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 to FileImage. 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 to NetworkImage. It will download the image from the network, and won't save it locally.

Use the package

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(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.

Important:

The directory where you want to save the image must already exist in the local disk. Otherwise, the image won't be saved.

Canvas

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
   
    (
        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.

Tests

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();

See also

  • 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 than cached_network_image, which uses SQLite under the hood.

Special Thanks: Hugo Passos helped me with the http override.

The Flutter packages I've authored:

My Medium Articles:

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

Comments
  • Local file is never used

    Local file is never used

    Right now the plugin always tries to load from the url and download instead of properly checking the local disk first. If you turn on debug you will see the Fetching image from and then the Reading image file after, even if the image has already been stored locally. I'm not sure if this is a simulator issue or it has something to do with the function _ifFileExistsLocally using existsSync instead of exists.

    opened by OpticNectar 15
  • _MockHttpClientRequest missing abort implementation

    _MockHttpClientRequest missing abort implementation

    Hello Marc, simple and awesome this package. Now, on Flutter 1.22.0-10.0.pre.39 • channel master • (not tested in previous versions yet) it appears is missing abort implementation in this class:

    class _MockHttpClientRequest extends HttpClientRequest {

    // should add -> @override // should add -> void abort([Object exception, StackTrace stackTrace]) {}

    }

    As you can see here: https://github.com/dart-lang/sdk/issues/22265

    opened by abnerh69 14
  • When the network is lost the message

    When the network is lost the message "Reading image file ..." is printed but the image is not loaded

    When network is lost the message "Reading image file ..." is printed but the image doesn't load. With a network connection, the image is read from file and displayed properly.

    opened by RShpd 8
  • Doesn't work for dev Channel, Flutter version 1.15.20.

    Doesn't work for dev Channel, Flutter version 1.15.20.

    Compiler message: /C:/src/flutter/.pub-cache/hosted/pub.flutter-io.cn/network_to_file_image-2.2.8/lib/network_to_file_image.dart:750:8: Error: The method '_MockHttpHeaders.set' has fewer named arguments than those of overridden method 'HttpHeaders.set'. void set(String name, Object value) {} ^ org-dartlang-sdk:///third_party/dart/sdk/lib/_http/http.dart:703:8: Context: This is the overridden method ('set'). void set(String name, Object value, ^ /C:/src/flutter/.pub-cache/hosted/pub.flutter-io.cn/network_to_file_image-2.2.8/lib/network_to_file_image.dart:732:8: Error: The method '_MockHttpHeaders.add' has fewer named arguments than those of overridden method 'HttpHeaders.add'. void add(String name, Object value) {} ^ org-dartlang-sdk:///third_party/dart/sdk/lib/_http/http.dart:694:8: Context: This is the overridden method ('add'). void add(String name, Object value, ^

    Compiler message: /C:/src/flutter/.pub-cache/hosted/pub.flutter-io.cn/network_to_file_image-2.2.8/lib/network_to_file_image.dart:750:8: Error: The method '_MockHttpHeaders.set' has fewer named arguments than those of overridden method 'HttpHeaders.set'. void set(String name, Object value) {} ^ org-dartlang-sdk:///third_party/dart/sdk/lib/_http/http.dart:703:8: Context: This is the overridden method ('set'). void set(String name, Object value, ^ /C:/src/flutter/.pub-cache/hosted/pub.flutter-io.cn/network_to_file_image-2.2.8/lib/network_to_file_image.dart:732:8: Error: The method '_MockHttpHeaders.add' has fewer named arguments than those of overridden method 'HttpHeaders.add'. void add(String name, Object value) {} ^ org-dartlang-sdk:///third_party/dart/sdk/lib/_http/http.dart:694:8: Context: This is the overridden method ('add'). void add(String name, Object value, ^ Target kernel_snapshot failed: Exception: Errors during snapshot creation: null build failed.

    FAILURE: Build failed with an exception.

    • Where: Script 'C:\src\flutter\packages\flutter_tools\gradle\flutter.gradle' line: 840

    • What went wrong: Execution failed for task ':app:compileFlutterBuildDebug'.

    Process 'command 'C:\src\flutter\bin\flutter.bat'' finished with non-zero exit value 1

    • Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

    • Get more help at https://help.gradle.org

    BUILD FAILED in 14s Exception: Gradle task assembleDebug failed with exit code 1

    opened by 54lianxi 6
  • Image can not be loaded after errorBuilder was used

    Image can not be loaded after errorBuilder was used

    Problem: I use errorBuilder from Image to handle the exceptional case that url can not be loaded, e.g. no network. The error widget is displayed properly, but once I quit to the previous page, turn on network and come back again, it is still showing the error widget. It seems like _loadAsync() does not get called. Any idea what's going on?

    btw, I found this similar issue for Image.network(), but looks like it is fixed.

    My code:

    Image(
      image: NetworkToFileImage(
          url: imageUrl,
          file: file),
      errorBuilder: (context, error, stackTrace) {
        return AbsorbPointer(child: Text('Download image failed,'));
      },
    );
    
    bug 
    opened by PandaGeek1024 5
  • Another exception was thrown: Instance of 'DiagnosticsProperty'<void>

    Another exception was thrown: Instance of 'DiagnosticsProperty'

    Doctor summary (to see all details, run flutter doctor -v): [√] Flutter (Channel stable, 2.5.2, on Microsoft Windows [Version 10.0.22563.1], locale en-IN) [√] Android toolchain - develop for Android devices (Android SDK version 31.0.0) [√] Chrome - develop for the web [X] Visual Studio - develop for Windows X Visual Studio not installed; this is necessary for Windows development. Download at https://visualstudio.microsoft.com/downloads/. Please install the "Desktop development with C++" workload, including all of its default components [√] Android Studio (version 2020.3) [√] VS Code (version 1.64.2) [√] Connected device (4 available)

    The package is not working in release mode. It shows grey box in app. dfc696a6-9558-47cd-b174-a29bff38946c

    minSdkVersion 22 targetSdkVersion 30

    opened by abilashgupta 4
  • Flutter 2.5 compatibility

    Flutter 2.5 compatibility

    After upgrading from flutter 2.2 to 2.5 i am facing this error .

    ../../../.pub-cache/hosted/pub.dartlang.org/network_to_file_image-3.0.0/lib/network_to_file_image.dart:313:34: Error: A value of type 'Future Function(Uri, String, String)?' can't be assigned to a variable of type 'Future Function(Uri, String, String?)?' because 'String?' is nullable and 'String' isn't.

    • 'Future' is from 'dart:async'.
    • 'Uri' is from 'dart:core'. _realClient.authenticate = f;
    opened by kjawadDeveloper1 4
  • Error when I import import 'package:network_to_file_image/network_to_file_image.dart';

    Error when I import import 'package:network_to_file_image/network_to_file_image.dart';

    IOS build. I've tried beta, stable and master. I've downgraded flutter in multiple channels, I've removed all the versions cached of network_to_file image from my flutter directory. I've used this package in other apps, they won't compile either now.

    Xcode and flutter did just update in the last two days.

    Compiler message: ../../../flutter/flutter/.pub-cache/hosted/pub.dartlang.org/network_to_file_imag e-2.2.8/lib/network_to_file_image.dart:732:8: Error: The method '_MockHttpHeaders.add' has fewer named arguments than those of overridden method 'HttpHeaders.add'. void add(String name, Object value) {}
    ^
    org-dartlang-sdk:///third_party/dart/sdk/lib/_http/http.dart:695:8: Context: This is the overridden method ('add'). void add(String name, Object value,
    ^
    ../../../flutter/flutter/.pub-cache/hosted/pub.dartlang.org/network_to_file_imag e-2.2.8/lib/network_to_file_image.dart:750:8: Error: The method '_MockHttpHeaders.set' has fewer named arguments than those of overridden method 'HttpHeaders.set'. void set(String name, Object value) {}
    ^
    org-dartlang-sdk:///third_party/dart/sdk/lib/_http/http.dart:704:8: Context: This is the overridden method ('set'). void set(String name, Object value,

    Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel master, v1.18.0-6.0.pre.83, on Mac OS X 10.15.4 19E287, locale en-US) [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2) [✓] Xcode - develop for iOS and macOS (Xcode 11.4.1) [✓] Chrome - develop for the web [✓] Android Studio (version 3.6) [✓] VS Code (version 1.44.2) [✓] Connected device (4 available)

    opened by jodymac 4
  • image file storage persistent ?

    image file storage persistent ?

    Are images stored locally with this package persisted across reboots / restarts of the phone and app? I ask because debug logs seem to indicate that after every reboot / restart, all images are fetched from the network and subsequently read from file. The image files are there. Why are they read from the network OR am I just reading the logs incorrectly?

    Fetching image from: https://rxpillimage.nlm.nih.gov/RxImage/image/images/gallery/600/29300-0243-10_RXNAVIMAGE10_8A3DC52E.jpg Fetching image from: https://rxpillimage.nlm.nih.gov/RxImage/image/images/gallery/600/16729-0006-17_RXNAVIMAGE10_5812AC25.jpg Reading image file: /data/user/0/domainhere/app_flutter/images/308135.jpg Reading image file: /data/user/0/domainhere/app_flutter/images/198211.jpg

    opened by jonny7737 4
  • NoSuchMethodError: The method '<optimized out>' was called on null.

    NoSuchMethodError: The method '' was called on null.

    I'm receiving the following error on Sentry report (that's why I couldn't reproduce the error or provide details of parameters used):

    NoSuchMethodError NoSuchMethodError: The method '' was called on null. Receiver: null Tried calling: ()

    Crashed in non-app: painting.dart in ImmutableBuffer.fromUint8List binding.dart in PaintingBinding.instantiateImageCodec at line 97 network_to_file_image.dart in NetworkToFileImage._loadAsync at line 170 network_to_file_image.dart in NetworkToFileImage.load at line 123 image_provider.dart in ImageProvider.resolveStreamForKey. at line 504 image_cache.dart in ImageCache.putIfAbsent at line 355 image_provider.dart in ImageProvider.resolveStreamForKey at line 502 image_provider.dart in ImageProvider.resolve. at line 333

    One of the devices which is facing this issue:

    brand | "samsung" device | "on7xelte" display | "M1AJQ.G610MUBS7CTA1" hardware | "samsungexynos7870" id | "M1AJQ" isPhysicalDevice | true manufacturer | "samsung" model | "SM-G610M" product | "on7xelteub" supported32BitAbis | ["armeabi-v7a","armeabi"] supported64BitAbis | [] supportedAbis | ["armeabi-v7a","armeabi"]

    The code where I use the library:

    Container(
        decoration: BoxDecoration(
            image: DecorationImage(
                image: NetworkToFileImage(
                    url: image.remotePath,
                    file: File(image.localPath),
                ),
                fit: BoxFit.cover,
            ),
            borderRadius: BorderRadius.all(
                Radius.circular(radius),
            ),
        ),
    )
    
    opened by f2acode 3
  • Storing downloaded images in folder

    Storing downloaded images in folder

    This package has worked great! However, I would like to be able to store the downloaded images in an image directory rather than the root directory of the app with the word Documents prefixed and the package to look in that directory for the already downloaded image.

    This will allow for cleaner storage and the ability to delete the contents of the folder to create a refresh on all the images. I'm currently using it to download business logos that could change at any time to reflect seasons or years. If they keep the same name of the image but replace it, I will always be serving the old image.

    opened by jodymac 3
  • Please add future download url parameter.

    Please add future download url parameter.

    Like this package: https://pub.dev/packages/firebase_image

    Sometime, I can not get a url directly, but we can get a future. Please add future download url parameter. Like this:

    Image(
        image: NetworkToFileImage(
            futureUrl: firebaseStorageFutureUrl, 
            file: myFile,
        ),
    );
    

    or this:

    Image(
        image: NetworkToFileImage(
            firebasePath: "gs://bucket123/userIcon123.jpg", 
            file: myFile,
        ),
    );
    
    enhancement 
    opened by nlthing 1
Owner
Marcelo Glasberg
Marcelo Glasberg
PlutoGrid is a dataGrid that can be controlled by the keyboard on desktop and web. Of course, it works well on Android and IOS.

PlutoGrid is a dataGrid that can be controlled by the keyboard on desktop and web.

Manki Kim 453 Jan 4, 2023
Customizable Material and Cupertino buttons with progress indicators and more

future_button Customizable Material and Cupertino buttons with progress indicators and more.

Erzhan 33 Oct 13, 2022
Custom widgets and utils using Flutter framework widgets and Dart language

reuse_widgets_and_utils The custom widgets and utils using Flutter framework widgets and Dart programming language. Getting Started This project is a

null 1 Oct 29, 2021
The SpannableGrid is a Flutter widget that allows its cells to span columns and rows and supports moving cells inside the grid.

Spannable Grid The SpannableGrid is a Flutter widget that allows its cells to span columns and rows and supports moving cells inside the grid. Feature

Evgeny Cherkasov 17 Nov 7, 2022
Pure Dart and Flutter package for Android,IOS and Web

Fancy Flutter Alert Dialog Pure Dart and Flutter package for Android,IOS and Web A flutter Package to show custom alert Dialog,you can choose between

Dokkar Rachid Reda 119 Sep 23, 2022
A widget that can be dragged and scrolled in a single gesture and snapped to a list of extents.

Sliding Sheet A widget that can be dragged and scrolled in a single gesture and snapped to a list of extents. Click here to view the full example. Ins

null 396 Mar 10, 2022
React hooks for Flutter. Hooks are a new kind of object that manages a Widget life-cycles. They are used to increase code sharing between widgets and as a complete replacement for StatefulWidget.

English | Português Flutter Hooks A Flutter implementation of React hooks: https://medium.com/@dan_abramov/making-sense-of-react-hooks-fdbde8803889 Ho

Remi Rousselet 2.6k Dec 29, 2022
Flutter debug helper widget with common and custom actions

Flutter debug helper widget with common and custom actions

Stanislav Ilin 43 Dec 7, 2022
A draggable Flutter widget that makes implementing a Sliding up and fully-stretchable much easier.

Draggable Home A draggable Flutter widget that makes implementing a Sliding up and fully-stretchable much easier! Based on the Scaffold and Sliver. Us

Devs On Flutter 106 Dec 12, 2022
Flutter widgets and themes implementing the current macOS design language.

macos_ui Flutter widgets and themes implementing the current macOS design language. NOTE: This package depends on the excellent native_context_menu pl

Reuben Turner 1.1k Jan 7, 2023
Flutter widget for fetching, caching and refetching asynchronous data.

Flutter library for fetching, caching and invalidating asynchronous data Quick Features Fetch asynchronous data Data invalidation Optimistic response

null 32 Dec 24, 2022
Math rendering and editing in pure Flutter.

Flutter Math Math equation rendering in pure Dart & Flutter. This project aims to achieve maximum compatibility and fidelity with regard to the KaTeX

null 109 Dec 16, 2022
A collection of pixel-perfect iOS-styled components and properties for Flutter, following the official guidelines.

cupertinew ⚠️ Experimental and work in progress ⚠️ A collection of pixel-perfect iOS-styled components and properties for Flutter, following the offic

null 30 Nov 10, 2022
This repo is for anything that can be reusable in flutter like custom widgets 🟥, animations 🌟and more

Flutter Shortcuts This repo is for anything that can be reusable in flutter like custom widgets ?? , animations ?? and more. How to Use Just get the f

Abdelrahman Mostafa Elmarakby 91 Dec 3, 2022
A flutter carousel widget, support infinite scroll, and custom child widget.

carousel_slider A carousel slider widget. Features Infinite scroll Custom child widgets Auto play Supported platforms Flutter Android Flutter iOS Flut

Bart T 1 Nov 25, 2021
RFlutter Alert is super customizable and easy-to-use alert/popup dialogs for Flutter.

RFlutter Alert is super customizable and easy-to-use alert/popup dialogs for Flutter. You may create reusable alert styles or add buttons as much as you want with ease.

Ratel 362 Jan 1, 2023
Provider support for overlay, make it easy to build toast and In-App notification.

overlay_support Provider support for overlay, make it easy to build toast and In-App notification. this library support ALL platform Interaction If yo

Bin 340 Jan 1, 2023
A sliding up panel widget which can be used to show or hide content, beautiful and simple.

flutter_sliding_up_panel A sliding up panel widget which can be used to show or hide content, beautiful and simple. demo Getting Started dependencies:

null 25 Dec 12, 2022
A widget that displays a collection of dispersed and non-overlapping children

flutter_scatter A widget that displays a collection of dispersed and non-overlapping children. Can be used to create word clouds: Features Built-in de

Romain Rastel 85 Sep 27, 2022