11
11
12
12
#define KEY_URL @" url"
13
13
#define KEY_SAVED_DIR @" saved_dir"
14
- # define KEY_SEARCH_DIR @" search_dir "
14
+
15
15
#define KEY_FILE_NAME @" file_name"
16
16
#define KEY_PROGRESS @" progress"
17
17
#define KEY_ID @" id"
@@ -58,8 +58,6 @@ @implementation FlutterDownloaderPlugin
58
58
static int _step = 10 ;
59
59
static NSMutableDictionary <NSString *, NSMutableDictionary *> *_runningTaskById = nil ;
60
60
61
- static NSSearchPathDirectory const kDefaultSearchPathDirectory = NSDocumentDirectory;
62
-
63
61
@synthesize databaseQueue;
64
62
65
63
- (instancetype )init : (NSObject <FlutterPluginRegistrar> *)registrar ;
@@ -98,11 +96,6 @@ - (instancetype)init:(NSObject<FlutterPluginRegistrar> *)registrar;
98
96
99
97
_dbManager = [[DBManager alloc ] initWithDatabaseFilePath: dbPath];
100
98
101
- __typeof__ (self) __weak weakSelf = self;
102
- [self executeInDatabaseQueueForTask: ^{
103
- [weakSelf addDatabaseColumnForMakingFileCouldSaveInAnyDirectory ];
104
- }];
105
-
106
99
if (_runningTaskById == nil ) {
107
100
_runningTaskById = [[NSMutableDictionary alloc ] init ];
108
101
}
@@ -299,7 +292,9 @@ - (void)sendUpdateProgressForTaskId: (NSString*)taskId inStatus: (NSNumber*) sta
299
292
{
300
293
NSArray *args = @[@(_callbackHandle), taskId, status, progress];
301
294
if (initialized && _callbackHandle != 0 ) {
302
- [_callbackChannel invokeMethod: @" " arguments: args];
295
+ dispatch_async (dispatch_get_main_queue (), ^{
296
+ [self -> _callbackChannel invokeMethod: @" " arguments: args];
297
+ });
303
298
} else {
304
299
[_eventQueue addObject: args];
305
300
}
@@ -313,13 +308,6 @@ - (void)executeInDatabaseQueueForTask:(void (^)(void))task {
313
308
});
314
309
}
315
310
316
- + (NSArray <NSNumber *> *)avaliableCommonDirectories {
317
- return @[@(NSCachesDirectory),
318
- @(NSApplicationSupportDirectory),
319
- @(NSLibraryDirectory),
320
- @(kDefaultSearchPathDirectory ),
321
- @(NSDownloadsDirectory)];;
322
- }
323
311
324
312
- (BOOL )openDocumentWithURL : (NSURL *)url {
325
313
if (debug) {
@@ -384,13 +372,10 @@ - (NSURL*)fileUrlOf:(NSString*)taskId taskInfo:(NSDictionary*)taskInfo downloadT
384
372
return [self fileUrlFromDict: mutableTaskInfo];
385
373
}
386
374
387
- - (NSString *)absoluteSavedDirPathWithShortSavedDir : (NSString *)shortSavedDir searchPathDirectory : (NSSearchPathDirectory )searchPathDirectory {
388
- return [[NSSearchPathForDirectoriesInDomains (searchPathDirectory, NSUserDomainMask, YES ) firstObject ] stringByAppendingPathComponent: shortSavedDir];
389
- }
390
-
391
375
- (NSString *)sanitizeFilename : (nullable NSString *)filename {
392
376
// Define a list of allowed characters for filenames
393
- NSCharacterSet *allowedCharacters = [NSCharacterSet characterSetWithCharactersInString: @" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_." ];
377
+ NSCharacterSet *allowedCharacters = [[NSCharacterSet characterSetWithCharactersInString: @" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.() " ] invertedSet ];
378
+
394
379
if (filename == nil || [filename isEqual: [NSNull null ]] || [filename isEqualToString: @" " ]) {
395
380
NSString *defaultFilename = @" default_filename" ;
396
381
return defaultFilename;
@@ -423,39 +408,30 @@ - (NSString *)sanitizeFilename:(nullable NSString *)filename {
423
408
}
424
409
425
410
411
+ - (NSString *)absoluteSavedDirPath : (NSString *)savedDir {
412
+ return [[NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES ) firstObject ] stringByAppendingPathComponent: savedDir];
413
+ }
426
414
427
- - (NSArray *)shortenSavedDirPath : (NSString *)absolutePath {
415
+ - (NSString *)shortenSavedDirPath : (NSString *)absolutePath {
428
416
if (debug) {
429
417
NSLog (@" Absolute savedDir path: %@ " , absolutePath);
430
418
}
431
419
432
- for (NSNumber *element in self.class .avaliableCommonDirectories ) {
433
- NSString *shortSvedDirPath = [self shortenSavedDirPath: absolutePath searchPathDirectory: element.unsignedIntegerValue];
434
- if (shortSvedDirPath) {
435
- return @[shortSvedDirPath, element];
436
- }
437
- }
438
-
439
- return @[@" " , @(kDefaultSearchPathDirectory )];
440
- }
441
-
442
- - (NSString *)shortenSavedDirPath : (NSString *)absolutePath searchPathDirectory : (NSSearchPathDirectory )searchPathDirectory {
443
420
if (absolutePath) {
444
- NSString *searchDirPath = [NSSearchPathForDirectoriesInDomains (searchPathDirectory , NSUserDomainMask, YES ) firstObject ];
445
- if ([absolutePath isEqualToString: searchDirPath ]) {
421
+ NSString * documentDirPath = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory , NSUserDomainMask, YES ) firstObject ];
422
+ if ([absolutePath isEqualToString: documentDirPath ]) {
446
423
return @" " ;
447
424
}
448
- NSRange foundRank = [absolutePath rangeOfString: searchDirPath ];
425
+ NSRange foundRank = [absolutePath rangeOfString: documentDirPath ];
449
426
if (foundRank.length > 0 ) {
450
427
// we increase the location of range by one because we want to remove the file separator as well.
451
- NSString *shortenSavedDirPath = [absolutePath substringWithRange: NSMakeRange (foundRank.length + 1 , absolutePath.length - searchDirPath .length - 1 )];
428
+ NSString *shortenSavedDirPath = [absolutePath substringWithRange: NSMakeRange (foundRank.length + 1 , absolutePath.length - documentDirPath .length - 1 )];
452
429
return shortenSavedDirPath != nil ? shortenSavedDirPath : @" " ;
453
430
}
454
431
}
455
-
456
- return nil ;
457
- }
458
432
433
+ return absolutePath;
434
+ }
459
435
460
436
- (long long )currentTimeInMilliseconds
461
437
{
@@ -464,27 +440,7 @@ - (long long)currentTimeInMilliseconds
464
440
465
441
# pragma mark - Database Accessing
466
442
467
- // / Before version 1.11.1, FlutterDownloader only allows file to be saved in [NSDocumentDirectory]. This limits the freedom of development.
468
- // /
469
- // / This function serves two purposes:
470
- // /
471
- // / 1. Add a database column `search_dir` for determining common root directory such as the flowing directories
472
- // /
473
- // / - NSCachesDirectory
474
- // / - NSApplicationSupportDirectory
475
- // / - NSLibraryDirectory
476
- // / - NSDocumentDirectory
477
- // / - NSDownloadsDirectory
478
- // /
479
- // / 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).
480
- // /
481
- // / 2. Resolve previous compatibility issue
482
- - (void )addDatabaseColumnForMakingFileCouldSaveInAnyDirectory {
483
- [_dbManager addLazilyColumnForTable: " task"
484
- column: KEY_SEARCH_DIR.UTF8String
485
- type: " integer"
486
- defaultValue: [NSString stringWithFormat: @" %lu " , kDefaultSearchPathDirectory ].UTF8String]; // kDefaultSearchPathDirectory is [NSDocumentDirectory](9), this is compatible with previous FlutterDownloader versions.
487
- }
443
+
488
444
- (NSString *) escape : (NSString *) origin revert : (BOOL )revert
489
445
{
490
446
if ( origin == (NSString *)[NSNull null ] )
@@ -503,18 +459,16 @@ - (void)addNewTask:(NSString *)taskId
503
459
progress : (int )progress
504
460
filename : (NSString *)filename
505
461
savedDir : (NSString *)savedDir
506
- searchDir : (NSSearchPathDirectory )searchDir
507
462
headers : (NSString *)headers
508
463
resumable : (BOOL )resumable
509
464
showNotification : (BOOL )showNotification
510
465
openFileFromNotification : (BOOL )openFileFromNotification {
511
466
512
467
headers = [self escape: headers revert: NO ];
513
468
514
- 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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" ;
515
- NSNumber *searchDirValue = @(searchDir);
469
+ 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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" ;
516
470
NSString *sanitizedFileName = [self sanitizeFilename: filename];
517
- NSArray *values = @[taskId, url, @(status), @(progress), sanitizedFileName, savedDir, searchDirValue, headers, @(resumable ? 1 :0 ), @(showNotification ? 1 : 0 ), @(openFileFromNotification ? 1 : 0 ), @([self currentTimeInMilliseconds ])];
471
+ NSArray *values = @[taskId, url, @(status), @(progress), sanitizedFileName, savedDir, headers, @(resumable ? 1 :0 ), @(showNotification ? 1 : 0 ), @(openFileFromNotification ? 1 : 0 ), @([self currentTimeInMilliseconds ])];
518
472
519
473
[_dbManager executeQuery: query withParameters: values];
520
474
@@ -707,16 +661,9 @@ - (NSDictionary*) taskDictFromRecordArray:(NSArray*)record
707
661
int progress = [[record objectAtIndex: [_dbManager.arrColumnNames indexOfObject: @" progress" ]] intValue ];
708
662
NSString *url = [record objectAtIndex: [_dbManager.arrColumnNames indexOfObject: @" url" ]];
709
663
NSString *filename = [record objectAtIndex: [_dbManager.arrColumnNames indexOfObject: @" file_name" ]];
710
- NSString *shortSavedDir = [record objectAtIndex: [_dbManager.arrColumnNames indexOfObject: @" saved_dir" ]];
711
-
712
- NSString *searchDirStr = [record objectAtIndex: [_dbManager.arrColumnNames indexOfObject: KEY_SEARCH_DIR]];
713
- int searchDir = [searchDirStr intValue ];
714
- NSNumber *searchDirNum = [NSNumber numberWithInt: searchDir];
715
-
716
- NSString *savedDir = [self absoluteSavedDirPathWithShortSavedDir: shortSavedDir searchPathDirectory: searchDir];
717
-
664
+ NSString *savedDir = [self absoluteSavedDirPath: [record objectAtIndex: [_dbManager.arrColumnNames indexOfObject: @" saved_dir" ]]];
718
665
NSString *headers = @" " ;
719
- // in certain cases, headers column might not be available and will cause NSRangeException
666
+ // in certain cases, headers column might not be available and will cause NSRangeException
720
667
@try {
721
668
NSString *rawHeaders = [record objectAtIndex: [_dbManager.arrColumnNames indexOfObject: @" headers" ]];
722
669
headers = [self escape: rawHeaders revert: true ];
@@ -727,7 +674,7 @@ - (NSDictionary*) taskDictFromRecordArray:(NSArray*)record
727
674
int showNotification = [[record objectAtIndex: [_dbManager.arrColumnNames indexOfObject: @" show_notification" ]] intValue ];
728
675
int openFileFromNotification = [[record objectAtIndex: [_dbManager.arrColumnNames indexOfObject: @" open_file_from_notification" ]] intValue ];
729
676
long long timeCreated = [[record objectAtIndex: [_dbManager.arrColumnNames indexOfObject: @" time_created" ]] longLongValue ];
730
- 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 ];
677
+ 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 ];
731
678
} @catch (NSException *exception) {
732
679
NSLog (@" invalid task data: %@ " , exception);
733
680
return [NSDictionary dictionary ];
@@ -773,14 +720,8 @@ - (void) unqueueStatusEvents {
773
720
774
721
- (void )enqueueMethodCall : (FlutterMethodCall*)call result : (FlutterResult)result {
775
722
NSString *urlString = call.arguments [KEY_URL];
776
-
777
- NSString *savedDirFromSource = call.arguments [KEY_SAVED_DIR];
778
- NSArray *shortSavedDirArgs = [self shortenSavedDirPath: savedDirFromSource];
779
- NSString *shortSavedDir = shortSavedDirArgs[0 ];
780
- NSNumber *searchDirNum = shortSavedDirArgs[1 ];
781
- NSSearchPathDirectory searchDir = searchDirNum.unsignedIntegerValue ;
782
- NSString *savedDir = [self absoluteSavedDirPathWithShortSavedDir: shortSavedDir searchPathDirectory: searchDir];
783
-
723
+ NSString *savedDir = call.arguments [KEY_SAVED_DIR];
724
+ NSString *shortSavedDir = [self shortenSavedDirPath: savedDir];
784
725
NSString *fileName = call.arguments [KEY_FILE_NAME];
785
726
NSString *headers = call.arguments [KEY_HEADERS];
786
727
NSNumber *showNotification = call.arguments [KEY_SHOW_NOTIFICATION];
@@ -794,7 +735,6 @@ - (void)enqueueMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result
794
735
urlString, KEY_URL,
795
736
fileName, KEY_FILE_NAME,
796
737
savedDir, KEY_SAVED_DIR,
797
- searchDirNum, KEY_SEARCH_DIR,
798
738
headers, KEY_HEADERS,
799
739
showNotification, KEY_SHOW_NOTIFICATION,
800
740
openFileFromNotification, KEY_OPEN_FILE_FROM_NOTIFICATION,
@@ -806,7 +746,7 @@ - (void)enqueueMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result
806
746
__typeof__ (self) __weak weakSelf = self;
807
747
808
748
[self executeInDatabaseQueueForTask: ^{
809
- [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 ]];
749
+ [weakSelf addNewTask: taskId url: urlString status: STATUS_ENQUEUED progress: 0 filename: fileName savedDir: shortSavedDir headers: headers resumable: NO showNotification: [showNotification boolValue ] openFileFromNotification: [openFileFromNotification boolValue ]];
810
750
}];
811
751
result (taskId);
812
752
[self sendUpdateProgressForTaskId: taskId inStatus: @(STATUS_ENQUEUED) andProgress: @0 ];
0 commit comments