How to do file operations (create/write/update/delete files) using the Flutter "saf" Package

1.8k Views Asked by At

How to do file operations (create/write/update/delete files) using the Flutter "saf" Package.

link:- pub.dev/packages/saf

I didn't find any solutions on Google. I want to use Android "Storage Access Framework" and let users select a folder on External Storage. In this folder, I want to save my app files that users can access.

Previously I was using app-specific storage (Android/data/com.myapp). But from Android 11 users can't access this folder due to Security Update from Google.

Any solutions will be appreciated. Thanks in advance.

bool? isGranted = await saf.getDirectoryPermission(isDynamic: false);

if (isGranted != null && isGranted) {
  // Perform some file operations
  // **But How?**
} else {
  // failed to get the permission
}
3

There are 3 best solutions below

2
On BEST ANSWER

If you get the folder access by using Storage Access Framework then you can not perform file handling operations on this folder by using the dart: 'dart: io' package. Check URL: SAF root gives your application access to the corresponding storage, but only through the SAF API, not directly via the filesystem. Also, from Android 11 and above, without MANAGE_EXTERNAL_STORAGE permission, accessing data from external storage using java.io.File is almost completely deprecated.

I found two Packages that support Storage Access Framework in the flutter.

shared_storage: ^0.2.0

saf: ^1.0.3+3

shared_storage 0.2.0 provide us

Uri uri = await openDocumentTree(); 
List<UriPermission> persistedUris = await persistedUriPermissions();

and

/// Create a new file using the `SAF` API
final newDocumentFile = await createDocumentFile(
  mimeType: 'text/plain',
  content: 'My Plain Text Comment Created by shared_storage plugin',
  displayName: 'CreatedBySharedStorageFlutterPlugin',
  directory: anySelectedUriByTheOpenDocumentTreeAPI,
);

print(newDocumentFile);

By above method can create file by using writeAsString() instead of writeAsBytes(). But for creating an Image file we required writeAsBytes().

saf 1.0.3+3 having a method createFileAsBytes() in document_file.dart but not available for usage in current version.

But in the future, both packages will provide these APIs.

Solution: For now, I have solved this issue by using both packages simultaneously.

Add packages in your pubspec.yaml:

shared_storage: ^0.2.0

saf: ^1.0.3+3

And use the following code

void createFileBySAF(String fileName, Uint8List uint8list) {

  /*From: shared_storage: ^0.2.0*/
  Uri uri = await openDocumentTree(); 
  
  /*From: saf: ^1.0.3+3*/
  Map<String, dynamic> result = await MethodChannel('com.ivehement.plugins/saf/documentfile').invokeMapMethod<String, dynamic>('createFile', <String, dynamic>{
    'mimeType': 'any',
    'content': uint8list,
    'displayName': fileName,
    'directoryUri': '$uri',
  });
  print(result);
}

For the Update and Delete operations find the usage in https://github.com/ivehement/saf/blob/master/lib/src/storage_access_framework/document_file.dart

2
On

checkout this Link SAF is only use for permission handling. Write, read operation is performed by dart.

Find the correct local path

Future<String> get _localPath async {
 final directory = await getApplicationDocumentsDirectory();
 return directory.path;
  }

Create a reference to the file location

Future get _localFile async { final path = await _localPath; return File('$path/counter.txt'); }

** Write data to the file **

Future writeCounter(int counter) async { final file = await _localFile;

// Write the file return file.writeAsString('$counter'); }

2
On

First get permission for the directory on which operation to be performed using saf flutter package


import 'package:saf/saf.dart';

await Saf.getDynamicDirectoryPermission()

Files operation in Flutter using dart: io core package

Create

var myFile = File('file.txt');

Read

File('file.txt').readAsString().then((String contents) {
    print(contents);
  });

Write

final filename = 'file.txt';
var file = await File(filename).writeAsString('some content');

Delete

var myFile = File('file.txt');
myFile.delete();

Source: https://api.dart.dev/stable/2.16.1/dart-io/File-class.html