Flutter: moving files from local machine - flutter

Can you use flutter to move files from local machine? For example from C:\images\photo.png to C:\photos\photo.png?

Yes you can make files moving using Dart/Flutter, you need to import dart:io :
import "dart:io";
then you can use this method, you can understand what it does with the comments I wrote.
Future<File> moveFile(File originalFile, String targetPath) async {
try {
// This will try first to just rename the file if they are on the same directory,
return await originalFile.rename(targetPath);
} on FileSystemException catch (e) {
// if the rename method fails, it will copy the original file to the new directory and then delete the original file
final newFileInTargetPath = await originalFile.copy(targetPath);
await originalFile.delete();
return newFileInTargetPath;
}
}
final file = File("C:/images/photo.png");
final path = "C:/photos/";
await moveFile(file, path);
However, I will explain here what it does :
If your file is under the same path directory, then there is no need to move it, just rename them with the rename() method will work, if the file is in an else directory on your system, it will create a new File where it will copy that file to that path, Now we will have two copies of that File, one under the old path and the other under the new path, so we need to delete the old one with the delete() method, finally we returned the new file with return newFile;

Related

Writing to file in Flutter multiple times updates the file. Reading from the file always gives me the initial content

SOLVED FOR MY SITUATION. MORE INFORMATION HERE AND THEN ORIGINAL QUESTION BELOW.
===Solution===
Due to settings with Android external storage, the file_picker plugin creates a cache of the file you pick and stores it in a cache directory within the app storage location. It will not overwrite this for files with the same name on subsequent reads. So for my read/write app, the solution was to do await file.delete(); when I was done with the read operation. This ensures that the next read will then create a cached version with the updated contents
===Original Question===
I have some content in a database on a Flutter app I am using to just practice some new stuff in FLutter. I have an export button that gets this data, JSON encodes it, and writes it to a file.
If I change the content and then export a second time, I can open the file on my device and see the updated content. I also have an import button. When I press that, I use FilePicker to select a file, read the contents of the file, and then JSON decode the data into an object.
I print out the file.readAsString and see the content from the initial write.
If I manually delete the file between writes then it works. If I use file.delete() before the write, it does not work. What can I do to get the updated text when I read from the file?
Getting file to write to. (I am aware this will only work on Android as is and that's fine)
Future<File?> _getBackupDataFile(String pathToTryFirst, ExportData data) async {
Directory? directory = Directory(pathToTryFirst);
if (!await directory.exists()) directory = await getExternalStorageDirectory();
if ((await directory?.exists() ?? false) == false) {
showErrorDialog(context: context, body: "Unable to find directory to save file.");
return null;
}
return File("${directory?.path}/pm-account-backup.json");
}
Write to file as such (without the delete code):
Future<void> _writeDataToFile(ExportData data) async {
try {
File? file = await _getBackupDataFile('/storage/emulated/0/Download', data);
if(file == null) { return; }
await file.writeAsString(jsonEncode(data));
await showSuccessDialog(context: context, title: "Success", body: "${data.accounts.length} accounts backed up successfully.");
} catch (e) {
showErrorDialog(context: context, body: "Failed to write data to file.");
}
}
Simplified file pick:
FilePickerResult? result = await FilePicker.platform.pickFiles();
if (result != null) {
String path = result.files.single.path ?? '';
if((path).endsWith(".json")) {
return File(path);
}
}
Read from file as such:
String fileData = await file.readAsString();
print(fileData);
Solution for my question found after more information provided by #pskink
Due to settings with Android external storage, the file_picker plugin creates a cache of the file you pick and stores it in a cache directory within the app storage location. It will not overwrite this for files with the same name on subsequent reads. So for my read/write app, the solution was to do await file.delete(); when I was done with the read operation. This ensures that the next read will then create a cached version with the updated contents

FileSystemException: Cannot open file, path = 'storage/emulated/0/DCIM/docs/myPdf.pdf' (OS Error: Operation not permitted, errno = 1)

I am trying to create a pdf document and write my data in that file. The data is a list of int or uint type. Able to do the same for images but not pdf or doc file. All permissions are given and it works for images. My code is below -
Future <File> createDocFile(Uint8List fileData, String type) async
{
File file = new File(".pdf");
if(await PermissionHandler.checkPermission(Permission.storage)!=true){
Url.toastShow("Storage permission not found.");
await Permission.storage.request();
}
else {
await file.writeAsBytes(fileData);
print("PDF SAVED IN DEVICE");
Url.toastShow("PDF saved in device",Colors.green);
}
}
Whenever you create a new file the device can't automatically find it. You'd have to manually tell the device to refresh for the files. Before you'd have to refresh all the files in the device for it to get updated which was very inefficient, but now you could just send the path of the file that you want to get updated. You can use the media_scanner plugin to do so.
Or If you wanna do it yourself with kotlin then here's the code,
private fun broadcastFileUpdate(path: String){
context.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.fromFile(File(path))))
}

Flutter create a file and write its contents

I am working on an app which gathers text content from server and as the next step I am trying to save them into separate files to be saved with in apps storage. Storage is a folder called 'storage'. Inside storage, there is a 'fileList.txt' file which contains the list of files.
In pubspec.yaml I declared this folder in the assets as follows:
assets:
- storage/
And I can read it using the following function:
Future<String> readFileContent() async {
String response;
response =
await rootBundle.loadString('storage/fileList.txt');
return response;
}
To save the file I made use of online examples which use 'path_provider' package. However when I try to save one of the downloaded files for instance 'file4.dat' using the following functions, I encounter the following error. How can I resolve that problem?
saveFileLocally() async {
await _writeFile();
}
Future<Null> _writeFile() async {
await (await _getLocalFile()).writeAsString(vars.fileContents);
}
Future<File> _getLocalFile() async {
// get the path to the document directory.
String dir = (await PathProvider.getApplicationSupportDirectory()).path;
print('DIR :::: ' + dir);
return new File(
'$dir/storage/files/file' + vars.newFileID.toString() + '.dat');
}
The error is:
Unhandled Exception: FileSystemException: Cannot open file,
path = '/data/user/0/com.example.ferenova_flutter_app/files/storage/file4.dat'
(OS Error: No such file or directory, errno = 2)
Thanks guys and take care !!! :)
While checking out path_provider examples, I ran into this important detail:
Directory directory = Platform.isAndroid
? await getExternalStorageDirectory() //FOR ANDROID
: await getApplicationSupportDirectory(); //FOR iOS
This solved my problem. I am no longer using default rootBundle asset to process any external files.
I think you should check your paths.
storage/fileList.txt is not the same as $dir/storage/files/file' + vars.loadedFileID.toString() + '.dat'
you should try:
response =
await rootBundle.loadString('$dir/storage/files/file' + vars.loadedFileID.toString() + '.dat'');
Or something similar.
GL

How to upload to a specific folder in the Google Drive GoogleAPIs v3 in Dart?

I'm want to upload images to a specific folder.
This is the function i'm using right now to upload my files, it uploads them the to main folder:
import 'package:googleapis/drive/v3.dart' as driveV3;
Future upload(File file) async {
var client = await getHttpClient();
var drive = driveV3.DriveApi(client);
var response = await drive.files.create(
driveV3.File()..name = p.basename(file.absolute.path),
uploadMedia: driveV3.Media(file.openRead(), file.lengthSync())
);
}
What i want is a way to upload ALWAYS to a folder that can be created at the first time or something like that. what do i need to modify in the above function so i can specify a folder name EX: MyFolder and always uploads to it?
You are looking for the parents of the File class
This property takes a list of String. These strings are the folders you want to upload the file to. As it seems, a file can be uploaded in multiple folders.
So your code should look something like this:
Future upload(File file) async {
var client = await getHttpClient();
var drive = driveV3.DriveApi(client);
file.parents = ["folder_id"];
var response = await drive.files.create(
driveV3.File()..name = p.basename(file.absolute.path),
uploadMedia: driveV3.Media(file.openRead(), file.lengthSync())
);
}
On the documentation I quote:
The IDs of the parent folders which contain the file. If not specified
as part of a create request, the file will be placed directly in the
user's My Drive folder. If not specified as part of a copy request,
the file will inherit any discoverable parents of the source file.
Update requests must use the addParents and removeParents parameters
to modify the parents list.

Copying .sqlite db to documents directory on Phone

I have a routine that copies a local SQLite database (from the Android Studio Assets folder) to the phone's document directory.
The problem I have is that this code is not very good. Sometimes the database is copied completely, and sometimes it is copied partially, or not at all. Its very buggy and I have no idea on how to improve on it.
Many times I get an error saying that certain tables cannot be found.
Here is the code that Im using:
copyDB() async
{
// Construct a file path to copy database to
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, DBAssistanceClass.databaseName);
print('The DB path is: '+ path);
// Only copy if the database doesn't exist
if (FileSystemEntity.typeSync(path) == FileSystemEntityType.notFound)
{
try
{
print('Copying DB...');
// Load database from asset and copy
ByteData data = await rootBundle.load(
join('assets', DBAssistanceClass.databaseName));
List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
// Save copied asset to documents
await File(path).writeAsBytes(bytes);
}
catch (error)
{
print(error);
}
}
}
This is for flutter, and I cannot find anything at all in dart documentation to assist.
I think if it is important to flush when you write the file. There is an Opening an asset database document in sqflite with a complete example.