Skip to content

Commit 27932e5

Browse files
author
Salma
committed
fix fileName and crash
1 parent 9260ff5 commit 27932e5

File tree

4 files changed

+27
-199
lines changed

4 files changed

+27
-199
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: 25 additions & 85 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
}
@@ -299,7 +292,9 @@ - (void)sendUpdateProgressForTaskId: (NSString*)taskId inStatus: (NSNumber*) sta
299292
{
300293
NSArray *args = @[@(_callbackHandle), taskId, status, progress];
301294
if (initialized && _callbackHandle != 0) {
302-
[_callbackChannel invokeMethod:@"" arguments:args];
295+
dispatch_async(dispatch_get_main_queue(), ^{
296+
[self-> _callbackChannel invokeMethod:@"" arguments:args];
297+
});
303298
} else {
304299
[_eventQueue addObject:args];
305300
}
@@ -313,13 +308,6 @@ - (void)executeInDatabaseQueueForTask:(void (^)(void))task {
313308
});
314309
}
315310

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

324312
- (BOOL)openDocumentWithURL:(NSURL*)url {
325313
if (debug) {
@@ -384,13 +372,10 @@ - (NSURL*)fileUrlOf:(NSString*)taskId taskInfo:(NSDictionary*)taskInfo downloadT
384372
return [self fileUrlFromDict:mutableTaskInfo];
385373
}
386374

387-
- (NSString*)absoluteSavedDirPathWithShortSavedDir:(NSString*)shortSavedDir searchPathDirectory:(NSSearchPathDirectory)searchPathDirectory {
388-
return [[NSSearchPathForDirectoriesInDomains(searchPathDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:shortSavedDir];
389-
}
390-
391375
- (NSString *)sanitizeFilename:(nullable NSString *)filename {
392376
// Define a list of allowed characters for filenames
393-
NSCharacterSet *allowedCharacters = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_."];
377+
NSCharacterSet *allowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.() "] invertedSet];
378+
394379
if (filename == nil || [filename isEqual:[NSNull null]] || [filename isEqualToString:@""]) {
395380
NSString *defaultFilename = @"default_filename";
396381
return defaultFilename;
@@ -423,39 +408,30 @@ - (NSString *)sanitizeFilename:(nullable NSString *)filename {
423408
}
424409

425410

411+
- (NSString*)absoluteSavedDirPath:(NSString*)savedDir {
412+
return [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:savedDir];
413+
}
426414

427-
- (NSArray *)shortenSavedDirPath:(NSString*)absolutePath {
415+
- (NSString*)shortenSavedDirPath:(NSString*)absolutePath {
428416
if (debug) {
429417
NSLog(@"Absolute savedDir path: %@", absolutePath);
430418
}
431419

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 {
443420
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]) {
446423
return @"";
447424
}
448-
NSRange foundRank = [absolutePath rangeOfString:searchDirPath];
425+
NSRange foundRank = [absolutePath rangeOfString:documentDirPath];
449426
if (foundRank.length > 0) {
450427
// 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)];
452429
return shortenSavedDirPath != nil ? shortenSavedDirPath : @"";
453430
}
454431
}
455-
456-
return nil;
457-
}
458432

433+
return absolutePath;
434+
}
459435

460436
- (long long)currentTimeInMilliseconds
461437
{
@@ -464,27 +440,7 @@ - (long long)currentTimeInMilliseconds
464440

465441
# pragma mark - Database Accessing
466442

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+
488444
- (NSString*) escape:(NSString*) origin revert:(BOOL)revert
489445
{
490446
if ( origin == (NSString *)[NSNull null] )
@@ -503,18 +459,16 @@ - (void)addNewTask:(NSString *)taskId
503459
progress:(int)progress
504460
filename:(NSString *)filename
505461
savedDir:(NSString *)savedDir
506-
searchDir:(NSSearchPathDirectory)searchDir
507462
headers:(NSString *)headers
508463
resumable:(BOOL)resumable
509464
showNotification:(BOOL)showNotification
510465
openFileFromNotification:(BOOL)openFileFromNotification {
511466

512467
headers = [self escape:headers revert:NO];
513468

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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
516470
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])];
518472

519473
[_dbManager executeQuery:query withParameters:values];
520474

@@ -707,16 +661,9 @@ - (NSDictionary*) taskDictFromRecordArray:(NSArray*)record
707661
int progress = [[record objectAtIndex:[_dbManager.arrColumnNames indexOfObject:@"progress"]] intValue];
708662
NSString *url = [record objectAtIndex:[_dbManager.arrColumnNames indexOfObject:@"url"]];
709663
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"]]];
718665
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
720667
@try {
721668
NSString *rawHeaders = [record objectAtIndex:[_dbManager.arrColumnNames indexOfObject:@"headers"]];
722669
headers = [self escape:rawHeaders revert:true];
@@ -727,7 +674,7 @@ - (NSDictionary*) taskDictFromRecordArray:(NSArray*)record
727674
int showNotification = [[record objectAtIndex:[_dbManager.arrColumnNames indexOfObject:@"show_notification"]] intValue];
728675
int openFileFromNotification = [[record objectAtIndex:[_dbManager.arrColumnNames indexOfObject:@"open_file_from_notification"]] intValue];
729676
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];
731678
} @catch(NSException *exception) {
732679
NSLog(@"invalid task data: %@", exception);
733680
return [NSDictionary dictionary];
@@ -773,14 +720,8 @@ - (void) unqueueStatusEvents {
773720

774721
- (void)enqueueMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
775722
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];
784725
NSString *fileName = call.arguments[KEY_FILE_NAME];
785726
NSString *headers = call.arguments[KEY_HEADERS];
786727
NSNumber *showNotification = call.arguments[KEY_SHOW_NOTIFICATION];
@@ -794,7 +735,6 @@ - (void)enqueueMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result
794735
urlString, KEY_URL,
795736
fileName, KEY_FILE_NAME,
796737
savedDir, KEY_SAVED_DIR,
797-
searchDirNum, KEY_SEARCH_DIR,
798738
headers, KEY_HEADERS,
799739
showNotification, KEY_SHOW_NOTIFICATION,
800740
openFileFromNotification, KEY_OPEN_FILE_FROM_NOTIFICATION,
@@ -806,7 +746,7 @@ - (void)enqueueMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result
806746
__typeof__(self) __weak weakSelf = self;
807747

808748
[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]];
810750
}];
811751
result(taskId);
812752
[self sendUpdateProgressForTaskId:taskId inStatus:@(STATUS_ENQUEUED) andProgress:@0];

0 commit comments

Comments
 (0)