image_downloader 0.15.4

  • README.md
  • CHANGELOG.md
  • Example
  • Installing
  • Versions
  • 94

image_downloader #

Flutter plugin that downloads images and movies on the Internet and saves to Photo Library on iOS or specified directory on Android.
This will keep Exif(DateTimeOriginal) and GPS(Latitude, Longitude).

Getting Started #

ios #

Add the following keys to your Info.plist file, located in

  • NSPhotoLibraryUsageDescription - Specifies the reason for your app to access the user’s photo library. This is called Privacy - Photo Library Usage Description in the visual editor.
  • NSPhotoLibraryAddUsageDescription - Specifies the reason for your app to get write-only access to the user’s photo library. This is called Privacy - Photo Library Additions Usage Description in the visual editor.

Android #

Add this permission in AndroidManifest.xml. (If you call AndroidDestinationType#inExternalFilesDir(), This setting is not necessary.)

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Example #

Basic #

try {
  // Saved with this method.
  var imageId = await ImageDownloader.downloadImage("https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter.png");
  if (imageId == null) {
    return;
  }

  // Below is a method of obtaining saved image information.
  var fileName = await ImageDownloader.findName(imageId);
  var path = await ImageDownloader.findPath(imageId);
  var size = await ImageDownloader.findByteSize(imageId);
  var mimeType = await ImageDownloader.findMimeType(imageId);
} on PlatformException catch (error) {
  print(error)
}

The return value is as follows.

  • imageId of the saved image if saving succeeded.
  • null if not been granted permission.
  • Otherwise it is a PlatformException.

Custom #

You can specify the storage location.
(Currently, external storage is only supported on Android.)

Three directories by default are provided.

  • AndroidDestinationType.directoryDownloads -> Environment.DIRECTORY_DOWNLOADS on Android
  • AndroidDestinationType.directoryPictures -> Environment.DIRECTORY_PICTURES on Android
  • AndroidDestinationType.directoryDCIM -> Environment.DIRECTORY_DCIM on Android
  • AndroidDestinationType.directoryMovies -> Environment.DIRECTORY_MOVIES on Android

In addition, there is also custom.

For example, the following sources is stored in /storage/emulated/0/sample/custom/sample.gif.
(Depends on the device.)

await ImageDownloader.downloadImage(url,
                                    destination: AndroidDestinationType.custom('sample')                                  
                                    ..subDirectory("custom/sample.gif"),
        );

For example, the following sources is stored in /storage/emulated/0/Android/data/<applicationId>/files/sample/custom/sample.gifby calling inExternalFilesDir() .
(Depends on the device.)

 await ImageDownloader.downloadImage(url,
                                     destination: AndroidDestinationType.custom('sample')
                                     ..inExternalFilesDir()
                                     ..subDirectory("custom/sample.gif"),
         );

Note: inExternalFilesDir() will not require WRITE_EXTERNAL_STORAGE permission, but downloaded images will also be deleted when uninstalling.

Progress #

You can get the progress value.
Note: On iOS, onProgressUpdate cannot get imageId.

  @override
  void initState() {
    super.initState();

    ImageDownloader.callback(onProgressUpdate: (String imageId, int progress) {
      setState(() {
        _progress = progress;
      });
    });
  }

Downloading multiple files #

You can do it simply by using await .

var list = [
  "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/bigsize.jpg",
  "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter.jpg",
  "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter_transparent.png",
  "https://raw.githubusercontent.com/wiki/ko2ic/flutter_google_ad_manager/images/sample.gif",
  "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter_no.png",
  "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter.png",
];

List<File> files = [];

for (var url in list) {
  try {
    var imageId = await ImageDownloader.downloadImage(url);
    var path = await ImageDownloader.findPath(imageId);
    files.add(File(path));
  } catch (error) {
    print(error);
  }
}
setState(() {
  _mulitpleFiles.addAll(files);
});

Preview #

There is a open method to be able to immediately preview the download file.
If you call it, in the case of ios, a preview screen using UIDocumentInteractionController is displayed. In case of Android, it is displayed by Intent.

var imageId = await ImageDownloader.downloadImage(url);
var path = await ImageDownloader.findPath(imageId);
await ImageDownloader.open(path);

Note: in the case of android, to use this feature, the following settings are required.

Add the following within

        <provider
                android:name="com.ko2ic.imagedownloader.FileProvider"
                android:authorities="${applicationId}.image_downloader.provider"
                android:exported="false"
                android:grantUriPermissions="true">
            <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/provider_paths"/>
        </provider>

Add provider_paths.xml in android/app/src/main/res/xml/ .

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

Error Hnadling #

downloadImage() #

You can determine the type of error with PlatformException#code.

In the case of HTTP status error, the code is stored.
In the case of the file format is not supported, unsupported_file is stored.
There is an important point in the case of unsupported_file.
Even unsupported files are stored in a temporary directory.
It can be retrieved with error.details ["unsupported_file_path"]; .
Note: it will be deleted when you exit the app.

ImageDownloader.downloadImage(url).catchError((error) {
  if (error is PlatformException) {
    var path = "";
    if (error.code == "404") {
      print("Not Found Error.");
    } else if (error.code == "unsupported_file") {
      print("UnSupported FIle Error.");
      path = error.details["unsupported_file_path"];
    }
  }
})

open() #

If the file can not be previewed, the preview_error is stored in the code.

  await ImageDownloader.open(_path).catchError((error) {
    if (error is PlatformException) {
      if (error.code == "preview_error") {
        print(error.message);
      }
    }    
  });

Trouble Shooting #

https://github.com/ko2ic/image_downloader/wiki#trouble-shooting

0.15.4 #

  • Fixed an issue where progress was not displayed correctly

0.15.3 #

  • Fix crash with progress function

0.15.2 #

  • Add saving in Environment.DIRECTORY_MOVIES

0.15.1 #

  • Fix NSMutableData.count to NSMutableData.length .

0.15.0+1 #

  • Update README.md

0.15.0 #

  • Support downloading video.
  • Added the feature to be able to immediately preview the download file.

0.14.1 #

  • Fix bug when downloading multiple files.
  • Add samples of multiple files.

0.14.0 #

  • Add feature to get progress value.

0.13.4 #

  • Fix crash when MimeType cannot be determined.
    (It could not be retrieved from the file name due to a simple mistake)

0.13.3 #

  • Fix crash when MimeType cannot be determined.

0.13.2 #

  • Fix crash when calling downloadImage() after getting HTTP error on Android.

0.13.1 #

  • Fix to return correct file path on iOS.

0.13.0 #

  • Returned as code of PlatformException in case of Http Status Code error.(e.g. 404)
  • Delete remaining files in case of errors on Android.

0.12.1 #

  • Fix to returns when not been granted permission on Android.
  • Fix Kotlin's warning.

0.12.0 #

  • Be able to specify the destination in external storage on Android.

0.11.2+1 #

  • Update Document.

0.11.2 #

  • Bump Swift Version to 4.2.

0.11.1 #

  • Fixed bug that does't work when using another Plugin using onRequestPermissionsResult.

0.11.0 #

  • Breaking change. Changed the return value from bool to imageId. You can acquire saved image information by using imageId.
  • Added findName, findPath, findByteSize, findMimeType.

0.10.0 #

  • Breaking change. Migrate from the deprecated original Android Support Library to AndroidX. This shouldn't result in any functional changes, but it requires any Android apps using this plugin to also migrate if they're using the original support library.

0.9.2 #

  • fix broken link of sample image.

0.9.1 #

  • Fix warnings of Dart Analysis.
  • Describe some documents.
  • Update ImageDownloder to private constructor.

0.9.0 #

  • initial public release.

example/README.md

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

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_downloader/image_downloader.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _message = "";
  String _path = "";
  String _size = "";
  String _mimeType = "";
  File _imageFile;
  int _progress = 0;

  List<File> _mulitpleFiles = [];

  @override
  void initState() {
    super.initState();

    ImageDownloader.callback(onProgressUpdate: (String imageId, int progress) {
      setState(() {
        _progress = progress;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Center(
          child: SingleChildScrollView(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                Text('Progress: $_progress %'),
                Text(_message),
                Text(_size),
                Text(_mimeType),
                Text(_path),
                _path == ""
                    ? Container()
                    : Builder(
                        builder: (context) => RaisedButton(
                              onPressed: () async {
                                await ImageDownloader.open(_path).catchError((error) {
                                  Scaffold.of(context).showSnackBar(SnackBar(
                                    content: Text((error as PlatformException).message),
                                  ));
                                });
                              },
                              child: Text("Open"),
                            ),
                      ),
                RaisedButton(
                  onPressed: () {
                    _downloadImage("https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/bigsize.jpg");
                  },
                  child: Text("default destination"),
                ),
                RaisedButton(
                  onPressed: () {
                    _downloadImage(
                      "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter.png",
                      destination: AndroidDestinationType.directoryPictures
                        ..inExternalFilesDir()
                        ..subDirectory("sample.gif"),
                    );
                  },
                  child: Text("custom destination(only android)"),
                ),
                RaisedButton(
                  onPressed: () {
                    _downloadImage("https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter_no.png", whenError: true);
                  },
                  child: Text("404 error"),
                ),
                RaisedButton(
                  onPressed: () {
                    _downloadImage("https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/sample.mkv", whenError: true);
                    //_downloadImage("https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/sample.3gp");
                  },
                  child: Text("unsupported file error(only ios)"),
                ),
                RaisedButton(
                  onPressed: () {
                    //_downloadImage("https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/sample.mp4");
                    //_downloadImage("https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/sample.m4v");
                    _downloadImage("https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/sample.mov");
                  },
                  child: Text("movie"),
                ),
                RaisedButton(
                  onPressed: () async {
                    var list = [
                      "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/bigsize.jpg",
                      "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter.jpg",
                      "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter_transparent.png",
                      "https://raw.githubusercontent.com/wiki/ko2ic/flutter_google_ad_manager/images/sample.gif",
                      "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter_no.png",
                      "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter.png",
                      "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter_real_png.jpg",
                      "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/bigsize.jpg",
                      "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter.jpg",
                      "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter_transparent.png",
                      "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter_no.png",
                      "https://raw.githubusercontent.com/wiki/ko2ic/flutter_google_ad_manager/images/sample.gif",
                      "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter.png",
                      "https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter_real_png.jpg",
                    ];

                    List<File> files = [];

                    for (var url in list) {
                      try {
                        var imageId = await ImageDownloader.downloadImage(url);
                        var path = await ImageDownloader.findPath(imageId);
                        files.add(File(path));
                      } catch (error) {
                        print(error);
                      }
                    }
                    setState(() {
                      _mulitpleFiles.addAll(files);
                    });
                  },
                  child: Text("multiple downlod"),
                ),
                (_imageFile == null) ? Container() : Image.file(_imageFile),
                GridView.count(
                  crossAxisCount: 4,
                  shrinkWrap: true,
                  physics: BouncingScrollPhysics(),
                  children: List.generate(_mulitpleFiles.length, (index) {
                    return SizedBox(
                      width: 50,
                      height: 50,
                      child: Image.file(File(_mulitpleFiles[index].path)),
                    );
                  }),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Future<void> _downloadImage(String url, {AndroidDestinationType destination, bool whenError = false}) async {
    String fileName;
    String path;
    int size;
    String mimeType;
    try {
      String imageId;

      if (whenError) {
        imageId = await ImageDownloader.downloadImage(url).catchError((error) {
          if (error is PlatformException) {
            var path = "";
            if (error.code == "404") {
              print("Not Found Error.");
            } else if (error.code == "unsupported_file") {
              print("UnSupported FIle Error.");
              path = error.details["unsupported_file_path"];
            }
            setState(() {
              _message = error.toString();
              _path = path;
            });
          }

          print(error);
        }).timeout(Duration(seconds: 10), onTimeout: () {
          print("timeout");
        });
      } else {
        if (destination == null) {
          imageId = await ImageDownloader.downloadImage(url);
        } else {
          imageId = await ImageDownloader.downloadImage(
            url,
            destination: destination,
          );
        }
      }

      if (imageId == null) {
        return;
      }
      fileName = await ImageDownloader.findName(imageId);
      path = await ImageDownloader.findPath(imageId);
      size = await ImageDownloader.findByteSize(imageId);
      mimeType = await ImageDownloader.findMimeType(imageId);
    } on PlatformException catch (error) {
      setState(() {
        _message = error.message;
      });
      return;
    }

    if (!mounted) return;

    setState(() {
      var location = Platform.isAndroid ? "Directory" : "Photo Library";
      _message = 'Saved as "$fileName" in $location.\n';
      _size = 'size:     $size';
      _mimeType = 'mimeType: $mimeType';
      _path = path;

      if (!_mimeType.contains("video")) {
        _imageFile = File(path);
      }
    });
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  image_downloader: ^0.15.4

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:image_downloader/image_downloader.dart';
  
Version Uploaded Documentation Archive
0.15.4 May 29, 2019 Go to the documentation of image_downloader 0.15.4 Download image_downloader 0.15.4 archive
0.15.3 May 29, 2019 Go to the documentation of image_downloader 0.15.3 Download image_downloader 0.15.3 archive
0.15.2 Apr 22, 2019 Go to the documentation of image_downloader 0.15.2 Download image_downloader 0.15.2 archive
0.15.1 Apr 19, 2019 Go to the documentation of image_downloader 0.15.1 Download image_downloader 0.15.1 archive
0.15.0+1 Apr 18, 2019 Go to the documentation of image_downloader 0.15.0+1 Download image_downloader 0.15.0+1 archive
0.15.0 Apr 18, 2019 Go to the documentation of image_downloader 0.15.0 Download image_downloader 0.15.0 archive
0.14.1 Apr 15, 2019 Go to the documentation of image_downloader 0.14.1 Download image_downloader 0.14.1 archive
0.14.0 Apr 12, 2019 Go to the documentation of image_downloader 0.14.0 Download image_downloader 0.14.0 archive
0.13.4 Apr 12, 2019 Go to the documentation of image_downloader 0.13.4 Download image_downloader 0.13.4 archive
0.13.3 Apr 12, 2019 Go to the documentation of image_downloader 0.13.3 Download image_downloader 0.13.3 archive

All 23 versions...

Popularity:
Describes how popular the package is relative to other packages. [more]
89
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
95
Overall:
Weighted score of the above. [more]
94
Learn more about scoring.

We analyzed this package on Jun 17, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.3.2
  • pana: 0.12.18
  • Flutter: 1.5.4-hotfix.2

Platforms

Detected platforms: Flutter

References Flutter, and has no conflicting libraries.

Health suggestions

Format lib/image_downloader.dart.

Run flutter format to format lib/image_downloader.dart.

Maintenance issues and suggestions

Support latest dependencies. (-5 points)

The version constraint in pubspec.yaml does not support the latest published versions for 1 dependency.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0-dev.68.0 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.11
meta 1.1.6 1.1.7
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8