pl_image_downloader
A powerful Flutter plugin for downloading images with progress tracking, notification support, and background service capabilities.
Features
- 📥 Image Download: Download images from URLs with customizable file names
- 📊 Progress Tracking: Real-time download progress updates via streams
- 🔔 Notification Support: Display download progress in system notifications (Android)
- 🔄 Retry Mechanism: Automatic retry on download failures
- 📁 Multiple Directories: Save to different directories (Downloads, Pictures, Music, Movies, Podcasts)
- 🎨 Multiple Formats: Support for JPEG, PNG, GIF, SVG, and BMP images
- ⚡ Concurrent Downloads: Handle multiple download tasks simultaneously via
DownloadService - 🔧 Background Service: Download in background service mode (Android only)
- 💾 Storage Options: Choose between internal and external storage (Android)
Platform Support
| Platform | Support | Notes |
|---|---|---|
| Android | ✅ | --- |
| iOS | ✅ | --- |
Android Requirements
- Minimum SDK: Not specified (check
build.gradlefor details) - Permissions: Internet permission (automatically handled)
- Storage permissions: Required for saving files (handled automatically)
iOS Requirements
- Add some permission for iOS device
<key>NSPhotoLibraryAddUsageDescription</key>
<string>We need access to save images to your photo library.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to your photo library to select images for your posts.</string>
Installation
Add this to your package's pubspec.yaml file:
dependencies:
pl_image_downloader: ^0.0.1
Then run:
flutter pub get
Usage
Basic Usage with Downloader
import 'package:pl_image_downloader/pl_image_downloader.dart';
// Initialize downloader
final downloader = Downloader();
// Configure download settings
final config = DownloadConfiguration(
downloadMode: DownloadMode.normal,
mimeType: MimeType.imageJpeg,
downloadDirectory: DownloadDirectory.pictures,
isExternalStorage: false,
retryCount: 3,
notificationConfig: NotificationConfig(
title: 'Downloading Image',
body: 'Please wait...',
displayProgress: true,
),
);
await downloader.updateConfig(config);
// Watch download progress
downloader.watchProgress((progress) {
print('Download progress: $progress%');
});
// Download an image
final downloadInfo = DownloadInfo.create(
url: 'https://example.com/image.jpg',
fileName: 'my_image.jpg',
);
final result = await downloader.download(downloadInfo);
if (result?.isSuccess == true) {
print('Downloaded to: ${result?.path}');
} else {
print('Download failed: ${result?.errorMessage}');
}
// Dispose when done
downloader.dispose();
Advanced Usage with DownloadService
For handling multiple concurrent downloads:
import 'package:pl_image_downloader/pl_image_downloader.dart';
// Initialize download service
final downloadService = DownloadService();
// Initialize with configuration
await downloadService.init(
DownloadConfiguration(
downloadMode: DownloadMode.normal,
mimeType: MimeType.imagePng,
downloadDirectory: DownloadDirectory.downloads,
retryCount: 3,
),
);
// Download multiple images
final urls = [
'https://example.com/image1.jpg',
'https://example.com/image2.jpg',
'https://example.com/image3.jpg',
];
for (final url in urls) {
downloadService.download(
url: url,
fileName: 'image_${DateTime.now().millisecondsSinceEpoch}.jpg',
).then((result) {
if (result?.isSuccess == true) {
print('Downloaded: ${result?.path}');
}
});
// Listen to progress for each download
final info = DownloadInfo.create(url: url);
downloadService.listenProgress(info.id, (progress) {
print('Progress for ${info.id}: $progress%');
});
}
// Dispose when done
downloadService.dispose();
Complete Example
import 'package:flutter/material.dart';
import 'package:pl_image_downloader/pl_image_downloader.dart';
class ImageDownloaderExample extends StatefulWidget {
@override
_ImageDownloaderExampleState createState() => _ImageDownloaderExampleState();
}
class _ImageDownloaderExampleState extends State<ImageDownloaderExample> {
late Downloader _downloader;
int _progress = 0;
bool _isDownloading = false;
@override
void initState() {
super.initState();
_initializeDownloader();
}
Future<void> _initializeDownloader() async {
_downloader = Downloader();
final config = DownloadConfiguration(
downloadMode: DownloadMode.normal,
mimeType: MimeType.imageJpeg,
downloadDirectory: DownloadDirectory.pictures,
retryCount: 3,
);
await _downloader.updateConfig(config);
_downloader.watchProgress((progress) {
setState(() {
_progress = progress;
});
});
}
Future<void> _downloadImage() async {
setState(() {
_isDownloading = true;
_progress = 0;
});
final result = await _downloader.download(
DownloadInfo.create(
url: 'https://example.com/image.jpg',
fileName: 'downloaded_image.jpg',
),
);
setState(() {
_isDownloading = false;
});
if (result?.isSuccess == true) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Downloaded to: ${result?.path}')),
);
}
}
@override
void dispose() {
_downloader.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Image Downloader')),
body: Column(
children: [
if (_isDownloading)
LinearProgressIndicator(value: _progress / 100),
ElevatedButton(
onPressed: _isDownloading ? null : _downloadImage,
child: Text('Download Image'),
),
],
),
);
}
}
API Reference
Downloader
Simple interface for downloading images.
Methods
download(DownloadInfo downloadInfo): Download an imageupdateConfig(DownloadConfiguration config): Update download configurationwatchProgress(Function(int progress) callback): Watch download progressdispose(): Dispose the downloader
DownloadService
Advanced service for handling multiple concurrent downloads.
Methods
init(DownloadConfiguration? config): Initialize the download servicedownload({String? fileName, required String url}): Download an imagedownloadConfig(DownloadConfiguration config): Update configurationlistenProgress(int id, void Function(int progress) callback): Listen to progressgetStream(int id): Get download task streamgetTask(int id): Get download taskdispose(): Dispose the service
DownloadConfiguration
Configuration for download behavior.
Properties
saveName: Optional custom file nameisExternalStorage: Save to external storage (Android)downloadMode: Download mode (DownloadMode.normalorDownloadMode.runningBackgroundService)mimeType: MIME type of the imagenotificationConfig: Notification configurationretryCount: Number of retry attempts (default: 3)downloadDirectory: Target directory for saving
DownloadInfo
Information about a download request.
Factory
DownloadInfo.create({required String url, String? fileName}): Create download info
DownloadResult
Result of a download operation.
Properties
path: File path of downloaded imagefileName: Name of the downloaded filedirectoryResult: Directory where file was savedisSuccess: Whether download was successfulerrorMessage: Error message if download failed
Enums
DownloadMode
normal: Standard download moderunningBackgroundService: Background service mode (Android only)
DownloadDirectory
downloads: Downloads directorypictures: Pictures directorymusic: Music directorymovies: Movies directorypodcasts: Podcasts directory
MimeType
imageJpeg: JPEG imagesimagePng: PNG imagesimageGif: GIF imagesimageSvgXml: SVG imagesimageBmp: BMP images
Notes
- This plugin currently work for both Android and iOS
- Background service mode (
DownloadMode.runningBackgroundService) is only available on Android - External storage option (
isExternalStorage) is Android-specific - Make sure to dispose
DownloaderorDownloadServiceinstances when done to free resources - The plugin handles permissions automatically, but ensure your app has the necessary permissions in
AndroidManifest.xml
License
See the LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.