Skip to content

Commit 72a3181

Browse files
author
Salma
committed
Merge remote-tracking branch 'origin/904'
2 parents e1d96a7 + 27932e5 commit 72a3181

File tree

4 files changed

+23
-215
lines changed

4 files changed

+23
-215
lines changed

example/lib/home_page.dart

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import 'dart:io';
22
import 'dart:isolate';
33
import 'dart:ui';
44

5-
import 'package:android_path_provider/android_path_provider.dart';
65
import 'package:device_info_plus/device_info_plus.dart';
76
import 'package:flutter/material.dart';
87
import 'package:flutter_downloader/flutter_downloader.dart';
@@ -363,48 +362,12 @@ class _MyHomePageState extends State<MyHomePage> {
363362

364363
Future<String?> _getSavedDir() async {
365364
String? externalStorageDirPath;
366-
367-
if (Platform.isAndroid) {
368-
try {
369-
externalStorageDirPath = await AndroidPathProvider.downloadsPath;
370-
} catch (err, st) {
371-
print('failed to get downloads path: $err, $st');
372-
373-
final directory = await getExternalStorageDirectory();
374-
externalStorageDirPath = directory?.path;
375-
}
376-
} else if (Platform.isIOS) {
377-
// var dir = (await _dirsOnIOS)[0]; // temporary
378-
// var dir = (await _dirsOnIOS)[1]; // applicationSupport
379-
// var dir = (await _dirsOnIOS)[2]; // library
380-
var dir = (await _dirsOnIOS)[3]; // applicationDocuments
381-
// var dir = (await _dirsOnIOS)[4]; // downloads
382-
383-
dir ??= await getApplicationDocumentsDirectory();
384-
externalStorageDirPath = dir.absolute.path;
385-
}
365+
externalStorageDirPath =
366+
(await getApplicationDocumentsDirectory()).absolute.path;
386367

387368
return externalStorageDirPath;
388369
}
389370

390-
Future<List<Directory?>> get _dirsOnIOS async {
391-
final temporary = await getTemporaryDirectory();
392-
final applicationSupport = await getApplicationSupportDirectory();
393-
final library = await getLibraryDirectory();
394-
final applicationDocuments = await getApplicationDocumentsDirectory();
395-
final downloads = await getDownloadsDirectory();
396-
397-
final dirs = [
398-
temporary,
399-
applicationSupport,
400-
library,
401-
applicationDocuments,
402-
downloads
403-
];
404-
405-
return dirs;
406-
}
407-
408371
@override
409372
Widget build(BuildContext context) {
410373
return Scaffold(

ios/Classes/DBManager.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@
2121

2222
-(NSArray *)loadDataFromDB:(NSString *)query withParameters:(NSArray *)parameters;
2323

24-
- (void)addLazilyColumnForTable:(const char *)table
25-
column:(const char *)column
26-
type:(const char *)type
27-
defaultValue:(const char *)defaultValue;
2824

2925
-(void)executeQuery:(NSString *)query withParameters:(NSArray *)parameters;
3026

ios/Classes/DBManager.m

Lines changed: 0 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -83,77 +83,6 @@ -(void)copyDatabaseIntoAppDirectory{
8383
}
8484
}
8585

86-
- (void)addLazilyColumnForTable:(const char *)table
87-
column:(const char *)column
88-
type:(const char *)type
89-
defaultValue:(const char *)defaultValue {
90-
91-
sqlite3 *sqlite3Database;
92-
NSString *databasePath = [self.appDirectory stringByAppendingPathComponent:self.databaseFilename];
93-
94-
if (debug) {
95-
NSLog(@"databasePath: %@", databasePath);
96-
}
97-
98-
int openDatabaseResult = sqlite3_open([databasePath UTF8String], &sqlite3Database);
99-
100-
if(openDatabaseResult != SQLITE_OK) {
101-
if(debug) {
102-
NSLog(@"error opening the database with error no.: %d", openDatabaseResult);
103-
}
104-
105-
return;
106-
}
107-
108-
if (debug) {
109-
NSLog(@"open DB successfully");
110-
}
111-
112-
sqlite3_stmt *compiledStatement;
113-
114-
const char *prefix = "select * from ";
115-
char *select = (char *)malloc(strlen(prefix) + strlen(table) + 1);
116-
sprintf(select, "%s%s", prefix, table);
117-
int prepareStatementResult = sqlite3_prepare_v2(sqlite3Database, (const char *)select, -1, &compiledStatement, NULL);
118-
if(prepareStatementResult == SQLITE_OK) {
119-
int isExistTargetColumn = -1;
120-
int totalColumns = sqlite3_column_count(compiledStatement);
121-
for (int i = 0; i < totalColumns; i++) {
122-
char *dbDataAsChars = (char *)sqlite3_column_text(compiledStatement, i);
123-
dbDataAsChars = (char *)sqlite3_column_name(compiledStatement, i);
124-
if (strcmp(dbDataAsChars, column) == 0) {
125-
isExistTargetColumn = 0;
126-
break;
127-
}
128-
}
129-
130-
if (isExistTargetColumn == -1) {
131-
const char *component = "alter table";
132-
const char *component1 = "add column";
133-
const char *component2 = "default";
134-
char *insert = (char *)malloc(strlen(component) + strlen(table) + strlen(component1) + strlen(column) + strlen(type) + strlen(column) + strlen(component2) + strlen(defaultValue) + 6 + 1);
135-
sprintf(insert, "%s %s %s %s %s %s %s", component, table, component1, column, type, component2, defaultValue);
136-
int execResult = sqlite3_exec(sqlite3Database, insert, NULL, NULL, NULL);
137-
if (execResult != SQLITE_OK) {
138-
if (debug) {
139-
fprintf(stderr, "sqlite3_exec error :%s\r\n", sqlite3_errmsg(sqlite3Database));
140-
}
141-
}
142-
} else {
143-
if (debug) {
144-
NSLog(@"DB table %s column %s already exists", table, column);
145-
}
146-
}
147-
} else {
148-
if (debug) {
149-
NSLog(@"%s", sqlite3_errmsg(sqlite3Database));
150-
}
151-
}
152-
153-
sqlite3_finalize(compiledStatement);
154-
sqlite3_close(sqlite3Database);
155-
}
156-
15786

15887
- (void)runQuery:(const char *)query withParameters:(NSArray *)parameters isQueryExecutable:(BOOL)queryExecutable {
15988

ios/Classes/FlutterDownloaderPlugin.m

Lines changed: 21 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
#define KEY_URL @"url"
1313
#define KEY_SAVED_DIR @"saved_dir"
14-
#define KEY_SEARCH_DIR @"search_dir"
14+
1515
#define KEY_FILE_NAME @"file_name"
1616
#define KEY_PROGRESS @"progress"
1717
#define KEY_ID @"id"
@@ -58,8 +58,6 @@ @implementation FlutterDownloaderPlugin
5858
static int _step = 10;
5959
static NSMutableDictionary<NSString*, NSMutableDictionary*> *_runningTaskById = nil;
6060

61-
static NSSearchPathDirectory const kDefaultSearchPathDirectory = NSDocumentDirectory;
62-
6361
@synthesize databaseQueue;
6462

6563
- (instancetype)init:(NSObject<FlutterPluginRegistrar> *)registrar;
@@ -98,11 +96,6 @@ - (instancetype)init:(NSObject<FlutterPluginRegistrar> *)registrar;
9896

9997
_dbManager = [[DBManager alloc] initWithDatabaseFilePath:dbPath];
10098

101-
__typeof__(self) __weak weakSelf = self;
102-
[self executeInDatabaseQueueForTask:^{
103-
[weakSelf addDatabaseColumnForMakingFileCouldSaveInAnyDirectory];
104-
}];
105-
10699
if (_runningTaskById == nil) {
107100
_runningTaskById = [[NSMutableDictionary alloc] init];
108101
}
@@ -315,13 +308,6 @@ - (void)executeInDatabaseQueueForTask:(void (^)(void))task {
315308
});
316309
}
317310

318-
+ (NSArray<NSNumber *> *)avaliableCommonDirectories {
319-
return @[@(NSCachesDirectory),
320-
@(NSApplicationSupportDirectory),
321-
@(NSLibraryDirectory),
322-
@(kDefaultSearchPathDirectory),
323-
@(NSDownloadsDirectory)];;
324-
}
325311

326312
- (BOOL)openDocumentWithURL:(NSURL*)url {
327313
if (debug) {
@@ -382,31 +368,10 @@ - (NSURL*)fileUrlOf:(NSString*)taskId taskInfo:(NSDictionary*)taskInfo downloadT
382368
return [self fileUrlFromDict:mutableTaskInfo];
383369
}
384370

385-
- (NSString*)absoluteSavedDirPathWithShortSavedDir:(NSString*)shortSavedDir searchPathDirectory:(NSSearchPathDirectory)searchPathDirectory {
386-
return [[NSSearchPathForDirectoriesInDomains(searchPathDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:shortSavedDir];
387-
}
388-
389371
- (NSString *)sanitizeFilename:(nullable NSString *)filename {
390372
// Define a list of allowed characters for filenames
391-
NSMutableCharacterSet *allowedCharacters = [[NSMutableCharacterSet alloc] init];
392-
393-
// Allow alphabetical characters (lowercase and uppercase)
394-
[allowedCharacters formUnionWithCharacterSet:[NSCharacterSet letterCharacterSet]];
395-
396-
// Allow digits
397-
[allowedCharacters addCharactersInRange:NSMakeRange('0', 10)]; // ASCII digits
398-
399-
// Allow additional characters: -_.()
400-
[allowedCharacters addCharactersInString:@"-_.()"];
373+
NSCharacterSet *allowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.() "] invertedSet];
401374

402-
// Allow empty spaces
403-
[allowedCharacters addCharactersInString:@" "];
404-
405-
// Remove the backslash (if you want to disallow it)
406-
[allowedCharacters removeCharactersInString:@"\\"];
407-
408-
// Now, you have a character set that allows the specified characters
409-
NSCharacterSet *finalCharacterSet = [allowedCharacters copy];
410375
if (filename == nil || [filename isEqual:[NSNull null]] || [filename isEqualToString:@""]) {
411376
NSString *defaultFilename = @"default_filename";
412377
return defaultFilename;
@@ -439,39 +404,30 @@ - (NSString *)sanitizeFilename:(nullable NSString *)filename {
439404
}
440405

441406

407+
- (NSString*)absoluteSavedDirPath:(NSString*)savedDir {
408+
return [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:savedDir];
409+
}
442410

443-
- (NSArray *)shortenSavedDirPath:(NSString*)absolutePath {
411+
- (NSString*)shortenSavedDirPath:(NSString*)absolutePath {
444412
if (debug) {
445413
NSLog(@"Absolute savedDir path: %@", absolutePath);
446414
}
447415

448-
for (NSNumber *element in self.class.avaliableCommonDirectories) {
449-
NSString *shortSvedDirPath = [self shortenSavedDirPath:absolutePath searchPathDirectory:element.unsignedIntegerValue];
450-
if (shortSvedDirPath) {
451-
return @[shortSvedDirPath, element];
452-
}
453-
}
454-
455-
return @[@"", @(kDefaultSearchPathDirectory)];
456-
}
457-
458-
- (NSString*)shortenSavedDirPath:(NSString*)absolutePath searchPathDirectory:(NSSearchPathDirectory)searchPathDirectory {
459416
if (absolutePath) {
460-
NSString *searchDirPath = [NSSearchPathForDirectoriesInDomains(searchPathDirectory, NSUserDomainMask, YES) firstObject];
461-
if ([absolutePath isEqualToString:searchDirPath]) {
417+
NSString* documentDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
418+
if ([absolutePath isEqualToString:documentDirPath]) {
462419
return @"";
463420
}
464-
NSRange foundRank = [absolutePath rangeOfString:searchDirPath];
421+
NSRange foundRank = [absolutePath rangeOfString:documentDirPath];
465422
if (foundRank.length > 0) {
466423
// we increase the location of range by one because we want to remove the file separator as well.
467-
NSString *shortenSavedDirPath = [absolutePath substringWithRange:NSMakeRange(foundRank.length + 1, absolutePath.length - searchDirPath.length - 1)];
424+
NSString *shortenSavedDirPath = [absolutePath substringWithRange:NSMakeRange(foundRank.length + 1, absolutePath.length - documentDirPath.length - 1)];
468425
return shortenSavedDirPath != nil ? shortenSavedDirPath : @"";
469426
}
470427
}
471-
472-
return nil;
473-
}
474428

429+
return absolutePath;
430+
}
475431

476432
- (long long)currentTimeInMilliseconds
477433
{
@@ -480,27 +436,7 @@ - (long long)currentTimeInMilliseconds
480436

481437
# pragma mark - Database Accessing
482438

483-
/// Before version 1.11.1, FlutterDownloader only allows file to be saved in [NSDocumentDirectory]. This limits the freedom of development.
484-
///
485-
/// This function serves two purposes:
486-
///
487-
/// 1. Add a database column `search_dir` for determining common root directory such as the flowing directories
488-
///
489-
/// - NSCachesDirectory
490-
/// - NSApplicationSupportDirectory
491-
/// - NSLibraryDirectory
492-
/// - NSDocumentDirectory
493-
/// - NSDownloadsDirectory
494-
///
495-
/// Definition of common root directory refers to [path_provider](https://github.com/flutter/packages/blob/main/packages/path_provider/path_provider/lib/path_provider.dart).
496-
///
497-
/// 2. Resolve previous compatibility issue
498-
- (void)addDatabaseColumnForMakingFileCouldSaveInAnyDirectory {
499-
[_dbManager addLazilyColumnForTable:"task"
500-
column:KEY_SEARCH_DIR.UTF8String
501-
type:"integer"
502-
defaultValue:[NSString stringWithFormat:@"%lu", kDefaultSearchPathDirectory].UTF8String]; // kDefaultSearchPathDirectory is [NSDocumentDirectory](9), this is compatible with previous FlutterDownloader versions.
503-
}
439+
504440
- (NSString*) escape:(NSString*) origin revert:(BOOL)revert
505441
{
506442
if ( origin == (NSString *)[NSNull null] )
@@ -519,18 +455,16 @@ - (void)addNewTask:(NSString *)taskId
519455
progress:(int)progress
520456
filename:(NSString *)filename
521457
savedDir:(NSString *)savedDir
522-
searchDir:(NSSearchPathDirectory)searchDir
523458
headers:(NSString *)headers
524459
resumable:(BOOL)resumable
525460
showNotification:(BOOL)showNotification
526461
openFileFromNotification:(BOOL)openFileFromNotification {
527462

528463
headers = [self escape:headers revert:NO];
529464

530-
NSString *query = @"INSERT INTO task (task_id, url, status, progress, file_name, saved_dir, search_dir, headers, resumable, show_notification, open_file_from_notification, time_created) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
531-
NSNumber *searchDirValue = @(searchDir);
465+
NSString *query = @"INSERT INTO task (task_id, url, status, progress, file_name, saved_dir, headers, resumable, show_notification, open_file_from_notification, time_created) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
532466
NSString *sanitizedFileName = [self sanitizeFilename:filename];
533-
NSArray *values = @[taskId, url, @(status), @(progress), sanitizedFileName, savedDir, searchDirValue, headers, @(resumable ? 1:0), @(showNotification ? 1 : 0), @(openFileFromNotification ? 1: 0), @([self currentTimeInMilliseconds])];
467+
NSArray *values = @[taskId, url, @(status), @(progress), sanitizedFileName, savedDir, headers, @(resumable ? 1:0), @(showNotification ? 1 : 0), @(openFileFromNotification ? 1: 0), @([self currentTimeInMilliseconds])];
534468

535469
[_dbManager executeQuery:query withParameters:values];
536470

@@ -723,16 +657,9 @@ - (NSDictionary*) taskDictFromRecordArray:(NSArray*)record
723657
int progress = [[record objectAtIndex:[_dbManager.arrColumnNames indexOfObject:@"progress"]] intValue];
724658
NSString *url = [record objectAtIndex:[_dbManager.arrColumnNames indexOfObject:@"url"]];
725659
NSString *filename = [record objectAtIndex:[_dbManager.arrColumnNames indexOfObject:@"file_name"]];
726-
NSString *shortSavedDir = [record objectAtIndex:[_dbManager.arrColumnNames indexOfObject:@"saved_dir"]];
727-
728-
NSString *searchDirStr = [record objectAtIndex:[_dbManager.arrColumnNames indexOfObject:KEY_SEARCH_DIR]];
729-
int searchDir = [searchDirStr intValue];
730-
NSNumber *searchDirNum = [NSNumber numberWithInt:searchDir];
731-
732-
NSString *savedDir = [self absoluteSavedDirPathWithShortSavedDir:shortSavedDir searchPathDirectory:searchDir];
733-
660+
NSString *savedDir = [self absoluteSavedDirPath:[record objectAtIndex:[_dbManager.arrColumnNames indexOfObject:@"saved_dir"]]];
734661
NSString *headers = @"";
735-
// in certain cases, headers column might not be available and will cause NSRangeException
662+
// in certain cases, headers column might not be available and will cause NSRangeException
736663
@try {
737664
NSString *rawHeaders = [record objectAtIndex:[_dbManager.arrColumnNames indexOfObject:@"headers"]];
738665
headers = [self escape:rawHeaders revert:true];
@@ -743,7 +670,7 @@ - (NSDictionary*) taskDictFromRecordArray:(NSArray*)record
743670
int showNotification = [[record objectAtIndex:[_dbManager.arrColumnNames indexOfObject:@"show_notification"]] intValue];
744671
int openFileFromNotification = [[record objectAtIndex:[_dbManager.arrColumnNames indexOfObject:@"open_file_from_notification"]] intValue];
745672
long long timeCreated = [[record objectAtIndex:[_dbManager.arrColumnNames indexOfObject:@"time_created"]] longLongValue];
746-
return [NSDictionary dictionaryWithObjectsAndKeys:taskId, KEY_TASK_ID, @(status), KEY_STATUS, @(progress), KEY_PROGRESS, url, KEY_URL, filename, KEY_FILE_NAME, headers, KEY_HEADERS, savedDir, KEY_SAVED_DIR, searchDirNum, KEY_SEARCH_DIR, [NSNumber numberWithBool:(resumable == 1)], KEY_RESUMABLE, [NSNumber numberWithBool:(showNotification == 1)], KEY_SHOW_NOTIFICATION, [NSNumber numberWithBool:(openFileFromNotification == 1)], KEY_OPEN_FILE_FROM_NOTIFICATION, @(timeCreated), KEY_TIME_CREATED, nil];
673+
return [NSDictionary dictionaryWithObjectsAndKeys:taskId, KEY_TASK_ID, @(status), KEY_STATUS, @(progress), KEY_PROGRESS, url, KEY_URL, filename, KEY_FILE_NAME, headers, KEY_HEADERS, savedDir, KEY_SAVED_DIR, [NSNumber numberWithBool:(resumable == 1)], KEY_RESUMABLE, [NSNumber numberWithBool:(showNotification == 1)], KEY_SHOW_NOTIFICATION, [NSNumber numberWithBool:(openFileFromNotification == 1)], KEY_OPEN_FILE_FROM_NOTIFICATION, @(timeCreated), KEY_TIME_CREATED, nil];
747674
} @catch(NSException *exception) {
748675
NSLog(@"invalid task data: %@", exception);
749676
return [NSDictionary dictionary];
@@ -789,14 +716,8 @@ - (void) unqueueStatusEvents {
789716

790717
- (void)enqueueMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
791718
NSString *urlString = call.arguments[KEY_URL];
792-
793-
NSString *savedDirFromSource = call.arguments[KEY_SAVED_DIR];
794-
NSArray *shortSavedDirArgs = [self shortenSavedDirPath:savedDirFromSource];
795-
NSString *shortSavedDir = shortSavedDirArgs[0];
796-
NSNumber *searchDirNum = shortSavedDirArgs[1];
797-
NSSearchPathDirectory searchDir = searchDirNum.unsignedIntegerValue;
798-
NSString *savedDir = [self absoluteSavedDirPathWithShortSavedDir:shortSavedDir searchPathDirectory:searchDir];
799-
719+
NSString *savedDir = call.arguments[KEY_SAVED_DIR];
720+
NSString *shortSavedDir = [self shortenSavedDirPath:savedDir];
800721
NSString *fileName = call.arguments[KEY_FILE_NAME];
801722
NSString *headers = call.arguments[KEY_HEADERS];
802723
NSNumber *showNotification = call.arguments[KEY_SHOW_NOTIFICATION];
@@ -810,7 +731,6 @@ - (void)enqueueMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result
810731
urlString, KEY_URL,
811732
fileName, KEY_FILE_NAME,
812733
savedDir, KEY_SAVED_DIR,
813-
searchDirNum, KEY_SEARCH_DIR,
814734
headers, KEY_HEADERS,
815735
showNotification, KEY_SHOW_NOTIFICATION,
816736
openFileFromNotification, KEY_OPEN_FILE_FROM_NOTIFICATION,
@@ -822,7 +742,7 @@ - (void)enqueueMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result
822742
__typeof__(self) __weak weakSelf = self;
823743

824744
[self executeInDatabaseQueueForTask:^{
825-
[weakSelf addNewTask:taskId url:urlString status:STATUS_ENQUEUED progress:0 filename:fileName savedDir:shortSavedDir searchDir:searchDir headers:headers resumable:NO showNotification: [showNotification boolValue] openFileFromNotification: [openFileFromNotification boolValue]];
745+
[weakSelf addNewTask:taskId url:urlString status:STATUS_ENQUEUED progress:0 filename:fileName savedDir:shortSavedDir headers:headers resumable:NO showNotification: [showNotification boolValue] openFileFromNotification: [openFileFromNotification boolValue]];
826746
}];
827747
result(taskId);
828748
[self sendUpdateProgressForTaskId:taskId inStatus:@(STATUS_ENQUEUED) andProgress:@0];

0 commit comments

Comments
 (0)