A Flutter package for downloading files on all platforms: Android, iOS, Web, Windows, macOS, and Linux.
Supports ALL file types - PDFs, music, videos, documents, archives, images, and any other format without restrictions.
โ
Universal Compatibility: Works on all Flutter platforms
โ
All File Types Supported: PDFs, music, videos, documents, archives, images, and any format
โ
Progress Tracking: Real-time download progress callbacks
โ
Platform-Optimized Storage: Uses appropriate directories for each platform
โ
Automatic Permissions: Handles storage permissions for mobile platforms
โ
Error Handling: Comprehensive error reporting and recovery
โ
Simple API: Easy-to-use interface with intuitive callbacks
Add this to your package's pubspec.yaml file:
dependencies:
universal_downloader: <latest>Then run:
flutter pub getUse downloadFromUrlStream() for all downloads - it's memory efficient, reliable, and works perfectly across all platforms:
import 'package:universal_downloader/universal_downloader.dart';
// RECOMMENDED: Use this for all downloads
final result = await UniversalDownloader.downloadFromUrlStream(
url: "https://example.com/file.zip",
filename: "file.zip",
onProgress: (progress) {
print("Progress: ${progress.percentage.toStringAsFixed(1)}%");
print("Downloaded: ${progress.downloadedBytes}/${progress.totalBytes} bytes");
},
onComplete: (filePath) {
print("โ
Download completed: $filePath");
},
onError: (error) {
print("โ Download failed: $error");
},
);
if (result.isSuccess) {
print("File saved at: ${result.filePath}");
} else {
print("Error: ${result.errorMessage}");
}import 'package:universal_downloader/universal_downloader.dart';
// Basic download without progress tracking
await UniversalDownloader.downloadFile(
url: "https://example.com/file.pdf",
fileName: "document.pdf",
);| Platform | Storage Location | Setup Required | Progress Tracking |
|---|---|---|---|
| Android | Downloads/Documents directory | โ | |
| iOS | Documents directory | โ None | โ |
| Web | Browser downloads | โ None | โ |
| Windows | %USERPROFILE%\Downloads |
โ None | โ |
| macOS | ~/Downloads |
โ | |
| Linux | ~/Downloads |
โ None | โ |
- Windows: Uses
USERPROFILE\Downloadsautomatically - Linux: Uses
HOME/Downloadsor XDG directories - iOS: Uses app Documents directory (sandboxed)
- Web: Uses browser's native download mechanism
Add to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />Add to macos/Runner/DebugProfile.entitlements and Release.entitlements:
<key>com.apple.security.files.downloads.read-write</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>For web-optimized downloads, use downloadUrl() which uses the browser's native download mechanism:
import 'package:universal_downloader/universal_downloader.dart';
// Web-optimized download using browser's native mechanism
await UniversalDownloader.downloadUrl(
url: "https://example.com/song.mp3",
filename: "song.mp3",
);Note: On native platforms, downloadUrl() automatically falls back to downloadFromUrlStream() for better compatibility.
Downloads files with streaming for better memory efficiency and progress tracking.
static Future<DownloadResult> downloadFromUrlStream({
required String url,
required String filename,
ProgressCallback? onProgress,
CompleteCallback? onComplete,
ErrorCallback? onError,
bool allowSelfSignedCertificate = false,
})Simple file download with optional progress tracking and callbacks.
static Future<DownloadResult> downloadFile({
required String url,
required String fileName,
ProgressCallback? onProgress,
CompleteCallback? onComplete,
ErrorCallback? onError,
bool saveToDocuments = false,
bool allowSelfSignedCertificate = false,
})Downloads a file from a Stream and saves it with the given filename.
static Future<void> downloadStream({
required Stream<int> stream,
required String filename,
})Downloads a file from binary data (Uint8List) and saves it with the given filename.
static Future<void> downloadData({
required Uint8List data,
required String filename,
})Downloads a file directly from a URL. Web-optimized, uses browser's native download.
static Future<void> downloadUrl({
required String url,
String? filename,
})Checks if the current platform supports directory selection.
static bool get supportsDirectorySelectionChecks if the current platform supports progress tracking.
static bool get supportsProgressTrackingGets the current platform name.
static String get platformNameclass DownloadProgress {
final int totalBytes;
final int downloadedBytes;
final double percentage;
final double? speed;
}class DownloadResult {
final String filePath;
final String url;
final String fileName;
final int totalBytes;
final bool isSuccess;
final String? errorMessage;
}try {
await UniversalDownloader.downloadFromUrlStream(
url: "https://example.com/file.zip",
filename: "file.zip",
);
} on NetworkDownloadException catch (e) {
print("Network error: $e");
} on PermissionDownloadException catch (e) {
print("Permission error: $e");
} on DownloadException catch (e) {
print("Download error: $e");
}Check out the example directory for a complete Flutter app:
cd example
flutter pub get
flutter runContributions are welcome! Please feel free to submit a Pull Request.
If you encounter any issues or need support, please create an issue on GitHub.
This project is licensed under the MIT License - see the LICENSE file for details.