패키지, 저장소 및 앱 카테고리 검색

패키지 상세v1.12.1

flutter_downloader

파일을 다운로드하는 것을 쉽게 만들어주는 강력한 플러그인입니다.

AndroidiOS
30일 다운로드
9.9만
좋아요
1.6천
Pub 점수
140

패키지 설치

flutter pub add flutter_downloader

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

Flutter Downloader는 Flutter 애플리케이션에서 파일 다운로드를 간편하게 만드는 강력한 플러그인입니다. 백그라운드 다운로드를 지원하고, 재시작 가능한 전송을 제공하며, 안드로이드 및 iOS 모두에 대한 진행률 추적 기능을 제공합니다. 이 플러그인은 네이티브 다운로드 매니저와 원활하게 통합되어 앱이 닫혀 있거나 디바이스가 잠겨 있어도 신뢰할 수 있는 성능을 보장합니다. 오프라인 콘텐츠, 미디어 파일 또는 대용량 데이터 패키지가 필요한 앱에 적합합니다.

사용 사례

  • 비디오나 문서와 같은 큰 파일 다운로드
  • 앱 콘텐츠에 오프라인 액세스 가능하게 하기
  • 앱 일시정지 중 백그라운드 다운로드 지원
  • 중단된 다운로드 재개
  • 여러 동시 다운로드 관리

주요 기능

  • 백그라운드 다운로드 지원
  • 다운로드 진행률 추적
  • 재개 가능한 다운로드
  • 크로스 플랫폼 호환성 (Android 및 iOS)
  • 네이티브 다운로드 관리자와의 통합

적합한 대상

  • 미디어 스트리밍 앱
  • 문서 관리 앱
  • 오프라인 우선 애플리케이션
  • 대용량 파일 다운로드가 필요한 앱
  • 강력한 다운로드 처리가 필요한 개발자

고려 사항

  • Android에서 적절한 권한이 필요합니다
  • iOS 백그라운드 모드에 대한 추가 구성이 필요할 수 있습니다
  • 파일 기반 다운로드에 제한됨(직접 URL 스트리밍 없음)
  • 플랫폼 전용 다운로드 서비스에 의존합니다
  • 많은 동시 다운로드 시 메모리 사용량 증가 가능성

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

flutter_community

Flutter Downloader

flutter_downloader on pub.dev

A plugin for creating and managing download tasks. Supports iOS and Android.

This plugin is using WorkManager on Android and NSURLSessionDownloadTask on iOS to run download tasks in background.

Development note:

The changes of external storage APIs in Android 11 cause some problems with the current implementation. I decide to re-design this plugin with new strategy to manage download file location. It is still in triage and discussion in this PR. It is very appreciated to have contribution and feedback from Flutter developer to get better design for the plugin.

Past Versions and SQL Injection Vulnerabilities

In 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.

It 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.

iOS integration

Required configuration:

The following steps require to open your ios project in Xcode.

  1. Enable background mode.

  1. Add sqlite library.

  1. Configure AppDelegate:

Objective-C:

/// AppDelegate.h
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>

@interface AppDelegate : FlutterAppDelegate

@end
// AppDelegate.m
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
#include "FlutterDownloaderPlugin.h"

@implementation AppDelegate

void registerPlugins(NSObject<FlutterPluginRegistry>* registry) {
  if (![registry hasPlugin:@"FlutterDownloaderPlugin"]) {
     [FlutterDownloaderPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterDownloaderPlugin"]];
  }
}

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];
  [FlutterDownloaderPlugin setPluginRegistrantCallback:registerPlugins];
  // Override point for customization after application launch.
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

@end

Or Swift:

import UIKit
import Flutter
import flutter_downloader

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    FlutterDownloaderPlugin.setPluginRegistrantCallback(registerPlugins)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

private func registerPlugins(registry: FlutterPluginRegistry) {
    if (!registry.hasPlugin("FlutterDownloaderPlugin")) {
       FlutterDownloaderPlugin.register(with: registry.registrar(forPlugin: "FlutterDownloaderPlugin")!)
    }
}

Optional configuration:
  • Support HTTP request: if you want to download file with HTTP request, you need to disable Apple Transport Security (ATS) feature. There're two options:
  1. Disable ATS for a specific domain only: (add the following code to your Info.plist file)
<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>www.yourserver.com</key>
    <dict>
      <!-- add this key to enable subdomains such as sub.yourserver.com -->
      <key>NSIncludesSubdomains</key>
      <true/>
      <!-- add this key to allow standard HTTP requests, thus negating the ATS -->
      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <!-- add this key to specify the minimum TLS version to accept -->
      <key>NSTemporaryExceptionMinimumTLSVersion</key>
      <string>TLSv1.1</string>
    </dict>
  </dict>
</dict>
  1. Completely disable ATS. Add the following to your Info.plist file)
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key><true/>
</dict>
  • Configure maximum number of concurrent tasks: the plugin allows 3 download tasks running at a moment by default (if you enqueue more than 3 tasks, there're only 3 tasks running, other tasks are put in pending state). You can change this number by adding the following code to your Info.plist file.
<!-- changes this number to configure the maximum number of concurrent tasks -->
<key>FDMaximumConcurrentTasks</key>
<integer>5</integer>
  • Localize notification messages: the plugin will send a notification message to notify user in case all files are downloaded while your application is not running in foreground. This message is English by default. You can localize this message by adding and localizing following message in Info.plist file. (you can find the detail of Info.plist localization in this link)
<key>FDAllFilesDownloadedMessage</key>
<string>All files have been downloaded</string>

Note:

  • This plugin only supports save files in NSDocumentDirectory

Android integration

You don't have to do anything extra to make the plugin work on Android.

There are although a few optional settings you might want to configure.

Open downloaded file from notification

To make tapping on notification open the downloaded file on Android, add the following code to AndroidManifest.xml:

<provider
    android:name="vn.hunghd.flutterdownloader.DownloadedFileProvider"
    android:authorities="${applicationId}.flutter_downloader.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths"/>
</provider>

Notes

  • You have to save your downloaded files in external storage (where the other applications have permission to read your files)
  • The downloaded files are only able to be opened if your device has at least one application that can read these file types (mp3, pdf, etc.)
Configure maximum number of concurrent download tasks

The plugin depends on WorkManager library and WorkManager depends on the number of available processor to configure the maximum number of tasks running at a moment. You can setup a fixed number for this configuration by adding the following code to your AndroidManifest.xml:

<!-- Begin FlutterDownloader customization -->
<!-- disable default Initializer -->
<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    tools:node="merge">
    <meta-data
        android:name="androidx.work.WorkManagerInitializer"
        android:value="androidx.startup"
        tools:node="remove" />
</provider>

<!-- declare customized Initializer -->
<provider
    android:name="vn.hunghd.flutterdownloader.FlutterDownloaderInitializer"
    android:authorities="${applicationId}.flutter-downloader-init"
    android:exported="false">
    <!-- changes this number to configure the maximum number of concurrent tasks -->
    <meta-data
        android:name="vn.hunghd.flutterdownloader.MAX_CONCURRENT_TASKS"
        android:value="5" />
</provider>
<!-- End FlutterDownloader customization -->
Localize strings in notifications

You can localize texts in download progress notifications by localizing following messages.

<string name="flutter_downloader_notification_started">Download started</string>
<string name="flutter_downloader_notification_in_progress">Download in progress</string>
<string name="flutter_downloader_notification_canceled">Download canceled</string>
<string name="flutter_downloader_notification_failed">Download failed</string>
<string name="flutter_downloader_notification_complete">Download complete</string>
<string name="flutter_downloader_notification_paused">Download paused</string>

You can learn more about localization on Android here.

Install .apk files

To open and install .apk files, your application needs REQUEST_INSTALL_PACKAGES permission. Add the following in your AndroidManifest.xml:

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

See also:

Usage

Import and initialize
import 'package:flutter_downloader/flutter_downloader.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();

  // Plugin must be initialized before using
  await FlutterDownloader.initialize(
    debug: true, // optional: set to false to disable printing logs to console (default: true)
    ignoreSsl: true // option: set to false to disable working with http links (default: false)
  );

  runApp(/*...*/)
}
Create new download task

The directory must be created in advance. After that, you need to provide the path of the directory in the savedDir parameter.

final taskId = await FlutterDownloader.enqueue(
  url: 'your download link',
  headers: {}, // optional: header send with url (auth token etc)
  savedDir: 'the path of directory where you want to save downloaded files',
  showNotification: true, // show download progress in status bar (for Android)
  openFileFromNotification: true, // click on notification to open downloaded file (for Android)
);
Update download progress
await FlutterDownloader.registerCallback(callback); // callback is a top-level or static function

Important

UI is rendered on the main isolate, while download events come from the background isolate (in other words, code in callback is run in the background isolate), so you have to handle the communication between two isolates. For example:

ReceivePort _port = ReceivePort();

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

  IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port');
  _port.listen((dynamic data) {
    String id = data[0];
    DownloadTaskStatus status = DownloadTaskStatus.fromInt(data[1]);
    int progress = data[2];
    setState((){ });
  });

  FlutterDownloader.registerCallback(downloadCallback);
}

@override
void dispose() {
  IsolateNameServer.removePortNameMapping('downloader_send_port');
  super.dispose();
}

@pragma('vm:entry-point')
static void downloadCallback(String id, int status, int progress) {
  final SendPort? send = IsolateNameServer.lookupPortByName('downloader_send_port');
  send?.send([id, status, progress]);
}

@pragma('vm:entry-point') must be placed above the callback function to avoid tree shaking in release mode for Android.

Load all download tasks
final List<DownloadTask>? tasks = await FlutterDownloader.loadTasks();
Load download tasks using a raw SQL query
final List<DownloadTask>? tasks = await FlutterDownloader.loadTasksWithRawQuery(query: query);

In order to parse data into DownloadTask object successfully, you should load data with all fields from the database (in the other words, use SELECT * ). For example:

SELECT * FROM task WHERE status=3

Below is the schema of the task table where flutter_downloader plugin stores information about download tasks

CREATE TABLE `task` (
  `id`  INTEGER PRIMARY KEY AUTOINCREMENT,
  `task_id` VARCHAR ( 256 ),
  `url` TEXT,
  `status`  INTEGER DEFAULT 0,
  `progress`  INTEGER DEFAULT 0,
  `file_name` TEXT,
  `saved_dir` TEXT,
  `resumable` TINYINT DEFAULT 0,
  `headers` TEXT,
  `show_notification` TINYINT DEFAULT 0,
  `open_file_from_notification` TINYINT DEFAULT 0,
  `time_created`  INTEGER DEFAULT 0
);
Cancel a task
FlutterDownloader.cancel(taskId: taskId);
Cancel all tasks
FlutterDownloader.cancelAll();
Pause a task
FlutterDownloader.pause(taskId: taskId);
Resume a task
FlutterDownloader.resume(taskId: taskId);

resume() will return a new taskId corresponding to a new background task that is created to continue the download process. You should replace the old taskId (that has paused status) by the new taskId to continue tracking the download progress.

Retry a failed task
FlutterDownloader.retry(taskId: taskId);

retry() will return a new taskId (just like resume())

Remove a task
FlutterDownloader.remove(taskId: taskId, shouldDeleteContent:false);
Open and preview a downloaded file
FlutterDownloader.open(taskId: taskId);

On Android, you can only open a downloaded file if it is placed in the external storage and there's at least one application that can read that file type on your device.

Bugs/Requests

Feel free to open an issue if you encounter any problems or think that the plugin is missing some feature.

Pull request are also very welcome!

카테고리

소스 저장소

이 패키지를 사용하는 프로젝트