flutter_downloader - Save the file with a name with special characters

316 Views Asked by At

I use the Flutter_downloader package to download from the API and the file name contains spaces and special characters. For example, "abc ông @.text" will be changed to "abc____.text" when saving the file.

My code:

await FlutterDownloader.enqueue(
  url: url,
  savedDir: localPath,
  saveInPublicStorage: true,
  fileName: ""abc ông @.text");

I want to keep its filename as "abc ông @.text"

2

There are 2 best solutions below

0
Brightcode On

From the package's behavior, there is no direct way to change this behavior in the package itself.

One possible workaround is to post-process the downloaded file and rename it to the desired filename. This can be done using the dart:io package's File class, specifically the rename method.

So you need to download it, get the path and rename it

Here's an example of how to do this:

import 'dart:io';

// Assume this is your downloaded file
File downloadedFile = File('path_to_downloaded_file/abc___\_.text');

// This is your desired filename
String desiredFileName = fileUrl.split("/").last //i.e "abc ông @.text";

// Rename the file
downloadedFile.renameSync('path_to_downloaded_file/$desiredFileName');

In this code, renameSync changes the name of the file at the given path, which should reflect your desired filename with spaces and special characters.

Please note that you need to handle the case where a file with the same name already exists in the directory. The renameSync method will throw an exception in such a case. If you want to overwrite existing files, you can use renameSync in combination with deleteSync:

if (File('path_to_downloaded_file/$desiredFileName').existsSync()) {
  File('path_to_downloaded_file/$desiredFileName').deleteSync();
}

downloadedFile.renameSync('path_to_downloaded_file/$desiredFileName');

This code checks if a file with the desired name already exists, and if it does, deletes it before renaming the downloaded file.

2
tomerpacific On

Looking inside the code of the Flutter Downloader package, you can see the following method:

- (NSString *)sanitizeFilename:(nullable NSString *)filename {
    // Define a list of allowed characters for filenames
    NSMutableCharacterSet *allowedCharacters = [[NSMutableCharacterSet alloc] init];

    // Allow alphabetical characters (lowercase and uppercase)
    [allowedCharacters formUnionWithCharacterSet:[NSCharacterSet letterCharacterSet]];

    // Allow digits
    [allowedCharacters addCharactersInRange:NSMakeRange('0', 10)]; // ASCII digits

    // Allow additional characters: -_.()
    [allowedCharacters addCharactersInString:@"-_.()"];

    // Allow empty spaces
    [allowedCharacters addCharactersInString:@" "];

    // Remove the backslash (if you want to disallow it)
    [allowedCharacters removeCharactersInString:@"\\"];

    // Now, you have a character set that allows the specified characters
    NSCharacterSet *finalCharacterSet = [allowedCharacters copy];
    if (filename == nil || [filename isEqual:[NSNull null]] || [filename isEqualToString:@""]) {
           NSString *defaultFilename = @"default_filename";
           return defaultFilename;
       }
    // Create a mutable string to build the sanitized filename
    NSMutableString *sanitizedFilename = [NSMutableString string];
    
    // Iterate over each character in the original filename
    for (NSUInteger i = 0; i < filename.length; i++) {
        unichar character = [filename characterAtIndex:i];
        
        // Check if the character is in the allowed set
        if ([allowedCharacters characterIsMember:character]) {
            // Append the allowed character to the sanitized filename
            [sanitizedFilename appendFormat:@"%C", character];
        } else {
            // Replace forbidden characters with an underscore
            [sanitizedFilename appendString:@"_"];
        }
    }
    
    // Ensure the sanitized filename is not empty
    if ([sanitizedFilename isEqualToString:@""]) {
        // Provide a default filename if the sanitized one is empty
        NSString *defaultFilename = @"default_filename";
        sanitizedFilename = [[NSMutableString alloc] initWithString:defaultFilename];
    }
    
    return sanitizedFilename;
}

As you can see, they have a method to sanitize the file name and this is why your special characters and spaces are replaced.