Code Monkey home page Code Monkey logo

network_to_file_image's Introduction

pub package

network_to_file_image

This package combines NetworkImage and FileImage to:

  • Download the image once from the URL,
  • Save it to the local file system,
  • Use the saved image from the file system from then on.

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

Import path_provider in your pubspec.yaml file:

path_provider: ^2.1.1 

Then use it to 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.

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

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

Special thanks: Hugo Passos helped 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://linkedin.com/in/marcglasberg/
https://twitter.com/glasbergmarcelo
https://stackoverflow.com/users/3411681/marcg
https://medium.com/@marcglasberg

network_to_file_image's People

Contributors

ali1ammar avatar marcglasberg avatar piedcipher avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

network_to_file_image's Issues

LateInitializationError: Local 'bytes' has not been initialized

I am always having this error. This is the full crashlytics console:

Fatal Exception: io.flutter.plugins.firebase.crashlytics.FlutterError
LateInitializationError: Local 'bytes' has not been initialized.. Error thrown resolving an image codec.
-------------------------------------------------------------------
LateError._throwLocalNotInitialized (dart:_internal)
NetworkToFileImage._loadAsync (network_to_file_image.dart:169)
NetworkToFileImage.load (network_to_file_image.dart:120)
ImageProvider.resolveStreamForKey.<fn> (image_provider.dart:539)
ImageCache.putIfAbsent (image_cache.dart:382)
ImageProvider.resolveStreamForKey (image_provider.dart:526)
ImageProvider.resolve.<fn> (image_provider.dart:374)
ImageProvider._createErrorHandlerAndKey.<fn> (image_provider.dart:488)
SynchronousFuture.then (synchronous_future.dart:41)

Failure after Flutter 1.17 upgrade

Compiler message:
../../dev-tools/flutter/.pub-cache/hosted/pub.dartlang.org/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,
^

Integration with flutter_map not working

Hello,
Please see my issue on flutter_map's repo about this issue. It includes code snippets and log outputs, as well as a more detailed report: link to repo issue.

The main gist of the issue is that the images are not taken from local storage when there is no internet.
If this sounds like something you could help with, I'd be very grateful.

Thanks.
Luka S

Error in network_to_file_image

Hello,

I use this package like in the example tab, but this error is showed in compilation:

Compiler message:
/C:/flutter/.pub-cache/hosted/pub.dartlang.org/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:/flutter/.pub-cache/hosted/pub.dartlang.org/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:/flutter/.pub-cache/hosted/pub.dartlang.org/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:/flutter/.pub-cache/hosted/pub.dartlang.org/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:\flutter\packages\flutter_tools\gradle\flutter.gradle' line: 833

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

Process 'command 'C:\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 23s
Exception: Gradle task assembleDebug failed with exit code 1

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

Save to local storage via a function

Hello

Is there any way to use it as a function instead of widget?

E.g. in the code I would have

// get data from file if exists
var myFile = await imageFile("file_name.png");

    // if the file doesn't exist - load it and save from the internet
    bool fileExists = await myFile.exists();
    if (!fileExists) {
      // here is a function reference I mean, it can be await async or sync function
      // but there should be a way to execute synchronous
     // because as a next step I need to read it from file, so the load should finish by then
      await NetworkToFileImage(
            url: "https://...",
            file: myFile),
      );
    // read data from the file after the load is finished
      await imageFile("file_name.png");
    }
    // and then get data from the file
    List<int> bytes = await myFile.readAsBytes();

Thank you!

Another exception was thrown: Instance of 'DiagnosticsProperty'<void>

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

_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: dart-lang/sdk#22265

Placeholder image or failure to load an image

Doubtless, I'm ignorant but I can't seem to detect when it's failed to download from the device AND from the web. This is especially relevant the first time it seeks a photo from the web.

I'd like to provide a placeholder image, my users have Avatars which are a perfectly acceptable fallback. But I can't fathom how to detect the failure situation. It's not returning null!

It would be great to know how to detect failure, or even be able to have a placeholder fall back image which works for failure.

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;

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.

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)

Web Support

Does this plugin support web and if so how?

Pub get failed because initial_login

Running latest Flutter, dart and network to file image 2.2.1
The current Dart SDK version is 2.7.0-dev.2.1.flutter-8b8894648f.

Because initial_login depends on network_to_file_image >=2.2.0 which requires SDK version >=2.7.0 <3.0.0, version solving failed.
pub get failed (1; Because initial_login depends on network_to_file_image >=2.2.0 which requires SDK version >=2.7.0 <3.0.0, version solving failed.)
exit code 1

I've been using a lower network to file image up to this point, but now can't even downgrade it to get it working again.

Default image

What if the connection failed and image is not downloaded yet it's better to use
a default image instead of throwing exception every time.

This plugin will not run on any of the new flutter versions

flutter version 1.6.7

file:///Users/jody/Flutter/flutter/.pub-cache/hosted/pub.dartlang.org/network_to
_file_image-1.0.4/lib/network_to_file_image.dart:110:31: Error: The argument
type 'Null Function(StringBuffer)' can't be assigned to the parameter type
'Iterable Function()'.

  • 'StringBuffer' is from 'dart:core'.
  • 'Iterable' is from 'dart:core'.
  • 'DiagnosticsNode' is from 'package:flutter/src/foundation/diagnostics.dart'
    ('file:///Users/jody/Flutter/flutter/packages/flutter/lib/src/foundation/diagno
    stics.dart').
    Try changing the type of the parameter, or casting the argument to
    'Iterable Function()'.
    informationCollector: (StringBuffer information)

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

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,'));
  },
);

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

Enhancement Request if I'm understanding the methodology correctly

Does this package only check the filename or does it check details of the file to determine if it needs to be downloaded from the network or served from the local directory?

if it only checks the filename, then...

Would it be possible to check for created date as well on image file to determine whether to download or keep serving from the local directory?

My app allows clients to upload a logo and an image and we give them the file names to upload based on their geographic location and database id. My dilemma is if they change either file, it will continue to serve the local copy rather than replaced file on the webserver source.

If this can't be done this way, then my options are...

  1. Allow the users to specify their own name which might create naming conflicts and will definitely increase tech support.
  2. Periodically clear the directory the local images are stored in which defeats my intention of keeping network data to a minimum by only downloading updated json data.

NoSuchMethodError: The method '<optimized out>' 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),
        ),
    ),
)

Assertion failure on Flutter 1.5

Using this string on Flutter 1.5.*
Image(image: NetworkToFileImage(url: "http://example.com/someFile.png", file: myFile))
gives assertion failure:
'package:flutter/src/painting/image_stream.dart': Failed assertion: line 121 pos 12: '_completer == null': is not true.
The same string works on Flutter 1.3.14 just fine

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.