{"id":13380313,"url":"https://github.com/fluttercommunity/flutter_downloader","last_synced_at":"2025-04-13T22:28:32.140Z","repository":{"id":39351707,"uuid":"136447801","full_name":"fluttercommunity/flutter_downloader","owner":"fluttercommunity","description":"Flutter Downloader - A plugin for creating and managing download tasks.","archived":false,"fork":false,"pushed_at":"2024-05-07T18:39:19.000Z","size":2376,"stargazers_count":889,"open_issues_count":304,"forks_count":505,"subscribers_count":24,"default_branch":"master","last_synced_at":"2024-05-20T22:49:15.940Z","etag":null,"topics":["android","background-worker","download-manager","downloader","flutter","flutter-plugin","hacktoberfest","ios"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/flutter_downloader","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fluttercommunity.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-06-07T08:38:12.000Z","updated_at":"2024-05-27T12:14:27.871Z","dependencies_parsed_at":"2023-09-23T13:54:24.261Z","dependency_job_id":"a1cebcac-51c6-4ef3-8758-8b75142473fb","html_url":"https://github.com/fluttercommunity/flutter_downloader","commit_stats":{"total_commits":327,"total_committers":64,"mean_commits":5.109375,"dds":0.5443425076452599,"last_synced_commit":"f0e3357c0ff97970c0972bf69fd6b41f23f7b0de"},"previous_names":["hnvn/flutter_downloader"],"tags_count":38,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttercommunity%2Fflutter_downloader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttercommunity%2Fflutter_downloader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttercommunity%2Fflutter_downloader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttercommunity%2Fflutter_downloader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fluttercommunity","download_url":"https://codeload.github.com/fluttercommunity/flutter_downloader/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248790392,"owners_count":21162003,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","background-worker","download-manager","downloader","flutter","flutter-plugin","hacktoberfest","ios"],"created_at":"2024-07-30T09:00:29.561Z","updated_at":"2025-04-13T22:28:32.096Z","avatar_url":"https://github.com/fluttercommunity.png","language":"Kotlin","readme":"[![flutter_community][fluttercommunity_badge]][fluttercommunity_link]\n\n# Flutter Downloader\n\n[![flutter_downloader on pub.dev][pub_badge]][pub_link]\n\nA plugin for creating and managing download tasks. Supports iOS and Android.\n\nThis plugin is using [`WorkManager`][work_manager] on Android and\n[`NSURLSessionDownloadTask`][url_session_download_task] on iOS to run download\ntasks in background.\n\n### _Development note_:\n\n_The changes of external storage APIs in Android 11 cause some problems with the\ncurrent implementation. I decide to re-design this plugin with new strategy to\nmanage download file location. It is still in triage and discussion in this\n[PR](https://github.com/fluttercommunity/flutter_downloader/pull/550). It is\nvery appreciated to have contribution and feedback from Flutter developer to get\nbetter design for the plugin._\n\n# Past Versions and SQL Injection Vulnerabilities\n\nIn previous versions of this package, there were known vulnerabilities related to SQL injection. SQL injection is a type of security vulnerability that can allow malicious users to manipulate SQL queries executed by an application, potentially leading to unauthorized access or manipulation of the database.\n\nIt is strongly recommended to upgrade to the latest version of this package to ensure that your application is not exposed to SQL injection vulnerabilities. The latest version contains the necessary security improvements and patches to mitigate such risks.\n\n## iOS integration\n\n### Required configuration:\n\nThe following steps require to open your `ios` project in Xcode.\n\n1. Enable background mode.\n\n\u003cimg width=\"512\"\nsrc=\"https://github.com/hnvn/flutter_downloader/blob/master/screenshot/enable_background_mode.png?raw=true\"/\u003e\n\n2. Add `sqlite` library.\n\n\u003cp\u003e\n    \u003cimg width=\"512\" src=\"https://github.com/hnvn/flutter_downloader/blob/master/screenshot/add_sqlite_1.png?raw=true\" /\u003e\n\u003c/p\u003e\n\u003cp style=\"margin-top:30;\"\u003e\n    \u003cimg width=\"512\" src=\"https://github.com/hnvn/flutter_downloader/blob/master/screenshot/add_sqlite_2.png?raw=true\" /\u003e\n\u003c/p\u003e\n\n3. Configure `AppDelegate`:\n\nObjective-C:\n\n```objective-c\n/// AppDelegate.h\n#import \u003cFlutter/Flutter.h\u003e\n#import \u003cUIKit/UIKit.h\u003e\n\n@interface AppDelegate : FlutterAppDelegate\n\n@end\n```\n\n```objective-c\n// AppDelegate.m\n#include \"AppDelegate.h\"\n#include \"GeneratedPluginRegistrant.h\"\n#include \"FlutterDownloaderPlugin.h\"\n\n@implementation AppDelegate\n\nvoid registerPlugins(NSObject\u003cFlutterPluginRegistry\u003e* registry) {\n  if (![registry hasPlugin:@\"FlutterDownloaderPlugin\"]) {\n     [FlutterDownloaderPlugin registerWithRegistrar:[registry registrarForPlugin:@\"FlutterDownloaderPlugin\"]];\n  }\n}\n\n- (BOOL)application:(UIApplication *)application\n    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n  [GeneratedPluginRegistrant registerWithRegistry:self];\n  [FlutterDownloaderPlugin setPluginRegistrantCallback:registerPlugins];\n  // Override point for customization after application launch.\n  return [super application:application didFinishLaunchingWithOptions:launchOptions];\n}\n\n@end\n\n```\n\nOr Swift:\n\n```swift\nimport UIKit\nimport Flutter\nimport flutter_downloader\n\n@UIApplicationMain\n@objc class AppDelegate: FlutterAppDelegate {\n  override func application(\n    _ application: UIApplication,\n    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?\n  ) -\u003e Bool {\n    GeneratedPluginRegistrant.register(with: self)\n    FlutterDownloaderPlugin.setPluginRegistrantCallback(registerPlugins)\n    return super.application(application, didFinishLaunchingWithOptions: launchOptions)\n  }\n}\n\nprivate func registerPlugins(registry: FlutterPluginRegistry) {\n    if (!registry.hasPlugin(\"FlutterDownloaderPlugin\")) {\n       FlutterDownloaderPlugin.register(with: registry.registrar(forPlugin: \"FlutterDownloaderPlugin\")!)\n    }\n}\n\n```\n\n### Optional configuration:\n\n- **Support HTTP request:** if you want to download file with HTTP request, you\n  need to disable Apple Transport Security (ATS) feature. There're two options:\n\n1. Disable ATS for a specific domain only: (add the following code to your\n   `Info.plist` file)\n\n```xml\n\u003ckey\u003eNSAppTransportSecurity\u003c/key\u003e\n\u003cdict\u003e\n  \u003ckey\u003eNSExceptionDomains\u003c/key\u003e\n  \u003cdict\u003e\n    \u003ckey\u003ewww.yourserver.com\u003c/key\u003e\n    \u003cdict\u003e\n      \u003c!-- add this key to enable subdomains such as sub.yourserver.com --\u003e\n      \u003ckey\u003eNSIncludesSubdomains\u003c/key\u003e\n      \u003ctrue/\u003e\n      \u003c!-- add this key to allow standard HTTP requests, thus negating the ATS --\u003e\n      \u003ckey\u003eNSTemporaryExceptionAllowsInsecureHTTPLoads\u003c/key\u003e\n      \u003ctrue/\u003e\n      \u003c!-- add this key to specify the minimum TLS version to accept --\u003e\n      \u003ckey\u003eNSTemporaryExceptionMinimumTLSVersion\u003c/key\u003e\n      \u003cstring\u003eTLSv1.1\u003c/string\u003e\n    \u003c/dict\u003e\n  \u003c/dict\u003e\n\u003c/dict\u003e\n```\n\n2. Completely disable ATS. Add the following to your `Info.plist` file)\n\n```xml\n\u003ckey\u003eNSAppTransportSecurity\u003c/key\u003e\n\u003cdict\u003e\n    \u003ckey\u003eNSAllowsArbitraryLoads\u003c/key\u003e\u003ctrue/\u003e\n\u003c/dict\u003e\n```\n\n- **Configure maximum number of concurrent tasks:** the plugin allows 3 download\n  tasks running at a moment by default (if you enqueue more than 3 tasks,\n  there're only 3 tasks running, other tasks are put in pending state). You can\n  change this number by adding the following code to your `Info.plist` file.\n\n```xml\n\u003c!-- changes this number to configure the maximum number of concurrent tasks --\u003e\n\u003ckey\u003eFDMaximumConcurrentTasks\u003c/key\u003e\n\u003cinteger\u003e5\u003c/integer\u003e\n```\n\n- **Localize notification messages:** the plugin will send a notification\n  message to notify user in case all files are downloaded while your application\n  is not running in foreground. This message is English by default. You can\n  localize this message by adding and localizing following message in\n  `Info.plist` file. (you can find the detail of `Info.plist` localization in\n  this [link][3])\n\n```xml\n\u003ckey\u003eFDAllFilesDownloadedMessage\u003c/key\u003e\n\u003cstring\u003eAll files have been downloaded\u003c/string\u003e\n```\n\n**Note:**\n\n- This plugin only supports save files in `NSDocumentDirectory`\n\n## Android integration\n\nYou don't have to do anything extra to make the plugin work on Android.\n\nThere are although a few optional settings you might want to configure.\n\n### Open downloaded file from notification\n\nTo make tapping on notification open the downloaded file on Android, add the\nfollowing code to `AndroidManifest.xml`:\n\n```xml\n\u003cprovider\n    android:name=\"vn.hunghd.flutterdownloader.DownloadedFileProvider\"\n    android:authorities=\"${applicationId}.flutter_downloader.provider\"\n    android:exported=\"false\"\n    android:grantUriPermissions=\"true\"\u003e\n    \u003cmeta-data\n        android:name=\"android.support.FILE_PROVIDER_PATHS\"\n        android:resource=\"@xml/provider_paths\"/\u003e\n\u003c/provider\u003e\n```\n\n**Notes**\n\n- You have to save your downloaded files in external storage (where the other\n  applications have permission to read your files)\n- The downloaded files are only able to be opened if your device has at least\n  one application that can read these file types (mp3, pdf, etc.)\n\n### Configure maximum number of concurrent download tasks\n\nThe plugin depends on `WorkManager` library and `WorkManager` depends on the\nnumber of available processor to configure the maximum number of tasks running\nat a moment. You can setup a fixed number for this configuration by adding the\nfollowing code to your `AndroidManifest.xml`:\n\n```xml\n\u003c!-- Begin FlutterDownloader customization --\u003e\n\u003c!-- disable default Initializer --\u003e\n\u003cprovider\n    android:name=\"androidx.startup.InitializationProvider\"\n    android:authorities=\"${applicationId}.androidx-startup\"\n    android:exported=\"false\"\n    tools:node=\"merge\"\u003e\n    \u003cmeta-data\n        android:name=\"androidx.work.WorkManagerInitializer\"\n        android:value=\"androidx.startup\"\n        tools:node=\"remove\" /\u003e\n\u003c/provider\u003e\n\n\u003c!-- declare customized Initializer --\u003e\n\u003cprovider\n    android:name=\"vn.hunghd.flutterdownloader.FlutterDownloaderInitializer\"\n    android:authorities=\"${applicationId}.flutter-downloader-init\"\n    android:exported=\"false\"\u003e\n    \u003c!-- changes this number to configure the maximum number of concurrent tasks --\u003e\n    \u003cmeta-data\n        android:name=\"vn.hunghd.flutterdownloader.MAX_CONCURRENT_TASKS\"\n        android:value=\"5\" /\u003e\n\u003c/provider\u003e\n\u003c!-- End FlutterDownloader customization --\u003e\n```\n\n### Localize strings in notifications\n\nYou can localize texts in download progress notifications by localizing\nfollowing messages.\n\n```xml\n\u003cstring name=\"flutter_downloader_notification_started\"\u003eDownload started\u003c/string\u003e\n\u003cstring name=\"flutter_downloader_notification_in_progress\"\u003eDownload in progress\u003c/string\u003e\n\u003cstring name=\"flutter_downloader_notification_canceled\"\u003eDownload canceled\u003c/string\u003e\n\u003cstring name=\"flutter_downloader_notification_failed\"\u003eDownload failed\u003c/string\u003e\n\u003cstring name=\"flutter_downloader_notification_complete\"\u003eDownload complete\u003c/string\u003e\n\u003cstring name=\"flutter_downloader_notification_paused\"\u003eDownload paused\u003c/string\u003e\n```\n\nYou can learn more about localization on Android [here][4].\n\n### Install .apk files\n\nTo open and install `.apk` files, your application needs\n`REQUEST_INSTALL_PACKAGES` permission. Add the following in your\n`AndroidManifest.xml`:\n\n```xml\n\u003cuses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\" /\u003e\n```\n\nSee also:\n\n- [Fix Cleartext Traffic error on Android 9 Pie][android_9_cleartext_traffic]\n\n## Usage\n\n### Import and initialize\n\n```dart\nimport 'package:flutter_downloader/flutter_downloader.dart';\n\nvoid main() {\n  WidgetsFlutterBinding.ensureInitialized();\n\n  // Plugin must be initialized before using\n  await FlutterDownloader.initialize(\n    debug: true, // optional: set to false to disable printing logs to console (default: true)\n    ignoreSsl: true // option: set to false to disable working with http links (default: false)\n  );\n\n  runApp(/*...*/)\n}\n```\n\n### Create new download task\n\nThe directory must be created in advance.\nAfter that, you need to provide the path of the directory in the `savedDir` parameter.\n\n```dart\nfinal taskId = await FlutterDownloader.enqueue(\n  url: 'your download link',\n  headers: {}, // optional: header send with url (auth token etc)\n  savedDir: 'the path of directory where you want to save downloaded files',\n  showNotification: true, // show download progress in status bar (for Android)\n  openFileFromNotification: true, // click on notification to open downloaded file (for Android)\n);\n```\n\n### Update download progress\n\n```dart\nawait FlutterDownloader.registerCallback(callback); // callback is a top-level or static function\n```\n\n**Important**\n\nUI is rendered on the main isolate, while download events come from the\nbackground isolate (in other words, code in `callback` is run in the background\nisolate), so you have to handle the communication between two isolates. For\nexample:\n\n```dart\nReceivePort _port = ReceivePort();\n\n@override\nvoid initState() {\n  super.initState();\n\n  IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port');\n  _port.listen((dynamic data) {\n    String id = data[0];\n    DownloadTaskStatus status = DownloadTaskStatus.fromInt(data[1]);\n    int progress = data[2];\n    setState((){ });\n  });\n\n  FlutterDownloader.registerCallback(downloadCallback);\n}\n\n@override\nvoid dispose() {\n  IsolateNameServer.removePortNameMapping('downloader_send_port');\n  super.dispose();\n}\n\n@pragma('vm:entry-point')\nstatic void downloadCallback(String id, int status, int progress) {\n  final SendPort? send = IsolateNameServer.lookupPortByName('downloader_send_port');\n  send?.send([id, status, progress]);\n}\n\n```\n\n`@pragma('vm:entry-point')` must be placed above the `callback` function to\navoid tree shaking in release mode for Android.\n\n### Load all download tasks\n\n```dart\nfinal List\u003cDownloadTask\u003e? tasks = await FlutterDownloader.loadTasks();\n```\n\n### Load download tasks using a raw SQL query\n\n```dart\nfinal List\u003cDownloadTask\u003e? tasks = await FlutterDownloader.loadTasksWithRawQuery(query: query);\n```\n\nIn order to parse data into `DownloadTask` object successfully, you should load\ndata with all fields from the database (in the other words, use `SELECT *` ).\nFor example:\n\n```SQL\nSELECT * FROM task WHERE status=3\n```\n\nBelow is the schema of the `task` table where `flutter_downloader` plugin stores\ninformation about download tasks\n\n```SQL\nCREATE TABLE `task` (\n  `id`  INTEGER PRIMARY KEY AUTOINCREMENT,\n  `task_id` VARCHAR ( 256 ),\n  `url` TEXT,\n  `status`  INTEGER DEFAULT 0,\n  `progress`  INTEGER DEFAULT 0,\n  `file_name` TEXT,\n  `saved_dir` TEXT,\n  `resumable` TINYINT DEFAULT 0,\n  `headers` TEXT,\n  `show_notification` TINYINT DEFAULT 0,\n  `open_file_from_notification` TINYINT DEFAULT 0,\n  `time_created`  INTEGER DEFAULT 0\n);\n```\n\n### Cancel a task\n\n```dart\nFlutterDownloader.cancel(taskId: taskId);\n```\n\n### Cancel all tasks\n\n```dart\nFlutterDownloader.cancelAll();\n```\n\n### Pause a task\n\n```dart\nFlutterDownloader.pause(taskId: taskId);\n```\n\n### Resume a task\n\n```dart\nFlutterDownloader.resume(taskId: taskId);\n```\n\n`resume()` will return a new `taskId` corresponding to a new background task\nthat is created to continue the download process. You should replace the old\n`taskId` (that has `paused` status) by the new `taskId` to continue tracking the\ndownload progress.\n\n### Retry a failed task\n\n```dart\nFlutterDownloader.retry(taskId: taskId);\n```\n\n`retry()` will return a new `taskId` (just like `resume()`)\n\n### Remove a task\n\n```dart\nFlutterDownloader.remove(taskId: taskId, shouldDeleteContent:false);\n```\n\n### Open and preview a downloaded file\n\n```dart\nFlutterDownloader.open(taskId: taskId);\n```\n\nOn Android, you can only open a downloaded file if it is placed in the external\nstorage and there's at least one application that can read that file type on\nyour device.\n\n## Bugs/Requests\n\nFeel free to open an issue if you encounter any problems or think that the\nplugin is missing some feature.\n\nPull request are also very welcome!\n\n[fluttercommunity_badge]: https://fluttercommunity.dev/_github/header/flutter_downloader\n[fluttercommunity_link]: https://github.com/fluttercommunity/community\n[pub_badge]: https://img.shields.io/pub/v/flutter_downloader.svg\n[pub_link]: https://pub.dartlang.org/packages/flutter_downloader\n[work_manager]: https://developer.android.com/topic/libraries/architecture/workmanager\n[url_session_download_task]: https://developer.apple.com/documentation/foundation/nsurlsessiondownloadtask?language=objc\n[android_9_cleartext_traffic]: https://medium.com/@son.rommer/fix-cleartext-traffic-error-in-android-9-pie-2f4e9e2235e6\n[3]: https://medium.com/@guerrix/info-plist-localization-ad5daaea732a\n[4]: https://developer.android.com/training/basics/supporting-devices/languages\n","funding_links":[],"categories":["Plugins"],"sub_categories":["Device"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffluttercommunity%2Fflutter_downloader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffluttercommunity%2Fflutter_downloader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffluttercommunity%2Fflutter_downloader/lists"}