다운로드 작업을 생성하고 관리하기 위한 플러그인입니다. iOS와 안드로이드를 지원합니다.
이 플러그인은 Android의 WorkManager 와 iOS의 NSURLSessionDownloadTask 사용하여 백그라운드에서 다운로드 작업을 실행합니다.
Android 11의 외부 저장소 API 변경으로 인해 현재 구현에 몇 가지 문제가 발생합니다. 나는 다운로드 파일 위치를 관리하기 위한 새로운 전략으로 이 플러그인을 다시 디자인하기로 결정했습니다. 이 PR에서는 아직 분류 및 논의 중입니다. 더 나은 플러그인 디자인을 얻기 위해 Flutter 개발자의 기여와 피드백을 받아주셔서 매우 감사합니다.
이 패키지의 이전 버전에는 SQL 삽입과 관련된 알려진 취약점이 있었습니다. SQL 주입은 악의적인 사용자가 애플리케이션에서 실행되는 SQL 쿼리를 조작할 수 있도록 허용하여 잠재적으로 데이터베이스에 대한 무단 액세스 또는 조작을 초래할 수 있는 일종의 보안 취약점입니다.
애플리케이션이 SQL 주입 취약점에 노출되지 않도록 하려면 이 패키지의 최신 버전으로 업그레이드하는 것이 좋습니다. 최신 버전에는 이러한 위험을 완화하는 데 필요한 보안 개선 사항과 패치가 포함되어 있습니다.
다음 단계에서는 Xcode에서 ios 프로젝트를 열어야 합니다.
백그라운드 모드를 활성화합니다.

sqlite 라이브러리를 추가합니다.


AppDelegate 구성:
목표-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 AppDelegatevoidregisterPlugins(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]; // 애플리케이션 실행 후 사용자 정의를 위해 지점을 재정의합니다. return [슈퍼 애플리케이션:application didFinishLaunchingWithOptions:launchOptions];
}@끝또는 스위프트:
UIKit 가져오기
Flutter 가져오기
import flutter_downloader@UIApplicationMain@objc class AppDelegate: FlutterAppDelegate { func 애플리케이션 재정의(
_ 애플리케이션: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: 모두]? ) -> Bool { 생성된PluginRegistrant.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")!) }}HTTP 요청 지원: HTTP 요청으로 파일을 다운로드하려면 ATS(Apple Transport Security) 기능을 비활성화해야 합니다. 두 가지 옵션이 있습니다:
특정 도메인에 대해서만 ATS를 비활성화합니다. ( Info.plist 파일에 다음 코드 추가)
<key>NSAppTransport보안</key>
<딕셔너리>
<key>NSExceptionDomains</key>
<딕셔너리>
<key>www.yourserver.com</key>
<dict> <!-- sub.yourserver.com과 같은 하위 도메인을 활성화하려면 이 키를 추가하세요 -->
<key>NSIncludesSubdomains</key>
<true/> <!-- 표준 HTTP 요청을 허용하려면 이 키를 추가하여 ATS를 무효화하세요 -->
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/> <!-- 허용할 최소 TLS 버전을 지정하려면 이 키를 추가하세요 -->
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
</dict>
</dict>
</dict> ATS를 완전히 비활성화합니다. Info.plist 파일에 다음을 추가하세요)
<key>NSAppTransport보안</key>
<딕셔너리>
<key>NSAllowsArbitraryLoads</key><true/>
</dict> 최대 동시 작업 수 구성: 플러그인은 기본적으로 한 번에 3개의 다운로드 작업 실행을 허용합니다(3개 이상의 작업을 대기열에 추가하면 3개의 작업만 실행되고 다른 작업은 보류 상태가 됩니다). Info.plist 파일에 다음 코드를 추가하여 이 번호를 변경할 수 있습니다.
<!-- 최대 동시 작업 수를 구성하기 위해 이 숫자를 변경합니다 --><key>FDMaximumConcurrentTasks</key> <integer>5</integer>
알림 메시지 현지화: 플러그인은 애플리케이션이 포그라운드에서 실행되지 않는 동안 모든 파일이 다운로드되는 경우 사용자에게 알리기 위해 알림 메시지를 보냅니다. 이 메시지는 기본적으로 영어입니다. Info.plist 파일에 다음 메시지를 추가하고 현지화하여 이 메시지를 현지화할 수 있습니다. (이 링크에서 Info.plist 현지화에 대한 자세한 내용을 확인할 수 있습니다)
<key>FDAllFilesDownloadedMessage</key> <string>모든 파일이 다운로드되었습니다</string>
메모:
이 플러그인은 NSDocumentDirectory 의 저장 파일만 지원합니다.
Android에서 플러그인이 작동하도록 하기 위해 추가로 수행할 작업은 없습니다.
구성할 수 있는 몇 가지 선택적 설정이 있습니다.
알림을 탭하여 Android에서 다운로드한 파일을 열려면 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"/>
</공급자>메모
다운로드한 파일을 외부 저장소에 저장해야 합니다(다른 응용 프로그램이 파일을 읽을 수 있는 권한이 있는 경우).
다운로드한 파일은 장치에 이러한 파일 형식(mp3, pdf 등)을 읽을 수 있는 응용 프로그램이 하나 이상 있는 경우에만 열 수 있습니다.
플러그인은 WorkManager 라이브러리에 따라 달라지며 WorkManager 사용 가능한 프로세서 수에 따라 동시에 실행되는 최대 작업 수를 구성합니다. AndroidManifest.xml 에 다음 코드를 추가하여 이 구성에 대한 고정 숫자를 설정할 수 있습니다.
<!-- FlutterDownloader 사용자 정의 시작 --><!-- 기본 초기화 비활성화 --><provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported ="false" 도구:노드="병합">
<meta-data android:name="androidx.work.WorkManagerInitializer" android:value="androidx.startup" 도구:node="remove" />
</provider><!-- 사용자 정의된 초기화 선언 --><provider android:name="vn.hunghd.flutterdownloader.FlutterDownloaderInitializer" android:authorities="${applicationId}.flutter-downloader-init" android:exported=" false"> <!-- 최대 동시 작업 수를 구성하기 위해 이 숫자를 변경합니다 -->
<meta-data android:name="vn.hunghd.flutterdownloader.MAX_CONCURRENT_TASKS" android:value="5" />
</provider><!-- FlutterDownloader 사용자 정의 종료 -->다음 메시지를 현지화하여 다운로드 진행률 알림의 텍스트를 현지화할 수 있습니다.
<string name="flutter_downloader_notification_started">다운로드 시작됨</string> <string name="flutter_downloader_notification_in_progress">다운로드 진행 중</string> <string name="flutter_downloader_notification_canceled">다운로드가 취소되었습니다</string> <string name="flutter_downloader_notification_failed">다운로드 실패</string> <string name="flutter_downloader_notification_complete">다운로드 완료</string> <string name="flutter_downloader_notification_paused">다운로드가 일시 중지되었습니다</string>
여기에서 Android의 현지화에 대해 자세히 알아볼 수 있습니다.
.apk 파일을 열고 설치하려면 애플리케이션에 REQUEST_INSTALL_PACKAGES 권한이 필요합니다. AndroidManifest.xml 에 다음을 추가합니다.
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
참조:
Android 9 Pie에서 일반 텍스트 트래픽 오류 수정
import 'package:flutter_downloader/flutter_downloader.dart';void main() { WidgetsFlutterBinding.ensureInitialized(); // Wait FlutterDownloader.initialize(를 사용하기 전에 플러그인을 초기화해야 합니다.
debug: true, // 선택 사항: 로그를 콘솔에 인쇄하지 않으려면 false로 설정합니다(기본값: true).
ignoreSsl: true // 옵션: http 링크 작업을 비활성화하려면 false로 설정합니다(기본값: false).
); 실행앱(/*...*/)
} 최종 taskId = FlutterDownloader.enqueue(
url: '다운로드 링크',
headers: {}, // 선택사항: URL과 함께 헤더 전송(인증 토큰 등)
saveDir: '다운로드한 파일을 저장하려는 디렉터리 경로',
showNotification: true, // 상태 표시줄에 다운로드 진행률 표시(Android의 경우)
openFileFromNotification: true, // 다운로드한 파일을 열려면 알림을 클릭하세요(Android의 경우));FlutterDownloader.registerCallback(콜백)을 기다립니다. // 콜백은 최상위 또는 정적 함수입니다.
중요한
UI는 기본 격리에서 렌더링되는 반면 다운로드 이벤트는 백그라운드 격리에서 발생하므로(즉, callback 의 코드가 백그라운드 격리에서 실행됨) 두 격리 간의 통신을 처리해야 합니다. 예를 들어:
receivePort _port = receiveport();@overridevoid initState() { super.initState(); IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port');
_port.listen((동적 데이터) { String id = data[0]; DownloadTaskStatus status = DownloadTaskStatus(data[1]); int Progress = data[2]; setState((){ });
}); FlutterDownloader.registerCallback(downloadCallback);
}@overridevoid 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, 상태, 진행률]);
} Android용 릴리스 모드에서 트리 흔들림을 방지하려면 @pragma('vm:entry-point') callback 함수 위에 배치해야 합니다.
최종 작업 = FlutterDownloader.loadTasks()를 기다립니다.
최종 작업 = FlutterDownloader.loadTasksWithRawQuery(query: query)를 기다립니다.
데이터를 DownloadTask 객체로 성공적으로 구문 분석하려면 데이터베이스의 모든 필드가 포함된 데이터를 로드해야 합니다(즉, SELECT * 사용). 예를 들어:
SELECT * FROM 작업 WHERE 상태=3
다음은 flutter_downloader 플러그인이 다운로드 작업에 대한 정보를 저장하는 task 테이블의 스키마입니다.
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 , `재개 가능` TINYINT DEFAULT 0, `headers` TEXT, `show_notification` TINYINT DEFAULT 0, `open_file_from_notification` TINYINT DEFAULT 0, `time_created` INTEGER DEFAULT 0);
FlutterDownloader.cancel(taskId: taskId);
FlutterDownloader.cancelAll();
FlutterDownloader.pause(taskId: taskId);
FlutterDownloader.resume(taskId: taskId);
resume() 다운로드 프로세스를 계속하기 위해 생성된 새 백그라운드 작업에 해당하는 새 taskId 반환합니다. 다운로드 진행 상황을 계속 추적하려면 이전 taskId ( paused 상태)를 새 taskId 로 바꿔야 합니다.
FlutterDownloader.retry(taskId: taskId);
retry() 새로운 taskId 반환합니다( resume() 과 유사).
FlutterDownloader.remove(taskId: taskId, shouldDeleteContent:false);
FlutterDownloader.open(taskId: taskId);
Android에서는 다운로드한 파일이 외부 저장소에 있고 장치에 해당 파일 형식을 읽을 수 있는 애플리케이션이 하나 이상 있는 경우에만 다운로드한 파일을 열 수 있습니다.
문제가 발생하거나 플러그인에 일부 기능이 없다고 생각되면 언제든지 문제를 열어주세요.
Pull Request도 매우 환영합니다!