smartdownloader 1.0.1
smartdownloader: ^1.0.1 copied to clipboard
A Flutter plugin for smart file downloading with progress, pause, resume, retry, and background support.
SmartDownloader #
smartdownloader is a Flutter package that parses JSON payloads, extracts URL fields, downloads files, and can render a built-in dashboard UI.
It is designed for production reliability: resume support, task restore after app restart, duplicate prevention, storage checks, and retry handling for network interruptions.
Features #
- Parse nested JSON and extract files from selected keys
- Validate URLs before starting downloads
- Resume partial downloads using
.partfiles - Restore unfinished tasks after app restart
- Skip duplicate downloads when file already exists
- Detect storage failures and fail gracefully
- Retry failed downloads with network recovery behavior
- Optional
DynamicDownloadDashboardUI with progress and retry actions
Installation #
dependencies:
smartdownloader: ^1.0.0
Quick Start (Dashboard UI) #
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:smartdownloader/dynamic_download_manager/dynamic_download_package.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(home: DemoWrapper());
}
}
class DemoWrapper extends StatefulWidget {
const DemoWrapper({super.key});
@override
State<DemoWrapper> createState() => _DemoWrapperState();
}
class _DemoWrapperState extends State<DemoWrapper> {
String? _downloadDir;
final String myApiResponse = '''
{
"data": [
{
"id": 1,
"store_image_url": "https://picsum.photos/id/237/200/300",
"adUrl": "https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/360/Big_Buck_Bunny_360_10s_1MB.mp4"
}
]
}
''';
@override
void initState() {
super.initState();
_initPath();
}
Future<void> _initPath() async {
final dir = await getApplicationDocumentsDirectory();
setState(() => _downloadDir = '${dir.path}/my_downloads');
}
@override
Widget build(BuildContext context) {
if (_downloadDir == null) {
return const Scaffold(body: Center(child: CircularProgressIndicator()));
}
return Scaffold(
body: DynamicDownloadDashboard(
jsonResponse: jsonDecode(myApiResponse),
extractKeys: const ['store_image_url', 'adUrl'],
customDownloadDir: _downloadDir!,
initialIsGridView: true,
initialThemeMode: ThemeMode.dark,
),
);
}
}
Headless API #
Use this when you do not want the dashboard UI.
final updatedJson = await DynamicDownloadManager.processResponse(
jsonResponse: myJsonPayload,
extractKeys: const ['store_image_url', 'adUrl'],
customDownloadDir: '/my/path',
headers: const {
'Authorization': 'Bearer <token>',
},
onTaskProgress: (url, progress, totalBytes) {
// progress: 0.0..1.0
// -1.0 => failed
// -2.0 => waiting for connection
debugPrint('$url => $progress ($totalBytes bytes)');
},
);
Manual retry:
await DynamicDownloadManager.retryDownload(
url: 'https://example.com/file.mp4',
customDownloadDir: '/my/path',
headers: const {
'Authorization': 'Bearer <token>',
},
onTaskProgress: (url, progress, totalBytes) {},
);
Reliability Behavior #
- Internet lost mid-download: task moves to waiting state and continues when online
- App closed/killed: task metadata is persisted and reused on next launch
- Storage full: operation fails with graceful status (no corrupted final file)
- Partial/corrupted downloads: writes to
.partfirst, renames only after success - No duplicates: if target file already exists, download is skipped as completed
Notes #
- Resume depends on server support for HTTP
Range; unsupported servers fall back to restart. - URL validation uses
HEADwith fallbackGETfor servers that blockHEAD.