Flutter - Save file visible to the user - file

In a Flutter project I create a pdf document. I can save the document in the path of the app.
But the user has no access to it. Alternatively, how can I save the file to another folder where the user sees it?
import 'package:path_provider/path_provider.dart';
Future<void> savePdfDocument() async {
final PdfCreater generatedPdf = PdfCreater(document);
final List<int> generatedPdfDocument = generatedPdf.buildPdf();
final String dir = (await getApplicationDocumentsDirectory()).path;
final String path = '$dir/example.pdf';
final File file = File(path);
file.writeAsBytesSync(generatedPdfDocument);
}

Use downloads_path_provider, on android it will save the file on Downloads.
for IOS, you need to use getApplicationDocumentsDirectoryfrom path_provider and add permissions on info.plist to make the folder visible to the user:
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>

This works like a charm
String documentsPath = '/storage/emulated/0/Documents/';
if (Platform.isIOS) {
Directory path = await getApplicationDocumentsDirectory();
documentsPath = path.path;
}
Also don't forgot to add this to pubspec
path_provider: 2.0.1

Also, be sure to test on a physical device, iOS emulator won't work.

Related

File path access permission

I want to access a folder other than root folders in UWP. The user will select the file with a file picker and then this file will be used for software update.
I am able to provide file selection as below. Then when I read this file, I get the error that I do not have permission to access it.
var picker = new FileOpenPicker();
picker.ViewMode = PickerViewMode.Thumbnail;
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
picker.FileTypeFilter.Add(".bin");
file = await picker.PickSingleFileAsync();
StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(file.Path);
StorageFile storageFile = await storageFolder.GetFileAsync(file.Name);
var fileStream = System.IO.File.Open(storageFile.Path, FileMode.Open);
If I manually copy the folder to the root folder and it works fine with the code below.
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
StorageFile storageFile = await storageFolder.GetFileAsync(file.Name);
var fileStream = System.IO.File.Open(storageFile.Path, FileMode.Open);
Solution for me in two ways. The first is to copy files from the outside to the root folder, the second way is to eliminate the access permission problem.Since it is a constantly changing file, I cannot import it into the project.
Uwp has strong file access restriction, File.open is not uwp api, it can only access two location, which are Application install directory and Application data locations, so your code works well when you copy this file to Application data location. Therefore, I suggest you could use StorageFile.OpenAsync method instead of File.open() to get the stream.

Flutter Web: Downloading file from URL without opening it

I want users to be able to download files uploaded by them. The problem is, certein files (like .pdf) are getting open in the browser, not downloaded. Is there any solution to just download a file in Flutter Web without opening it in the web browser?
Code that I'm using:
final anchor = AnchorElement(
href: url)
..setAttribute("download", fileName)
..click();
Following this answer, you can generate url from a string or from a list of int (bytes of file). Here is a short snipper that should work (from the answer above):
import 'dart:convert';
import 'dart:html' as html; // or package:universal_html/prefer_universal/html.dart
final text = 'this is the text file';
// prepare
final bytes = utf8.encode(text);
final blob = html.Blob([bytes]);
final url = html.Url.createObjectUrlFromBlob(blob);
final anchor = html.document.createElement('a') as html.AnchorElement
..href = url
..style.display = 'none'
..download = 'some_name.txt';
html.document.body.children.add(anchor);
// download
anchor.click();
// cleanup
html.document.body.children.remove(anchor);
html.Url.revokeObjectUrl(url);
Also, universal_html package is very handy to use html on all Flutter platforms. Using dart:html in a Flutter mobile app will make compiling fail.

How can I overwrite an assets image in Flutter having a source image?

I'm fairly new to Dart and Flutter, and I'm having trouble to overwrite an existing assets image from a source image.
My attempt:
try {
File localFile = File('assets/images/myImage.png');
localFile.writeAsBytesSync(originFile.readAsBytesSync());
catch (e) {
log(e.toString());
}
I get:
[log] FileSystemException: Cannot open file, path = 'assets/images/myImage.png' (OS Error: No such file or directory, errno = 2)
I did define the assets folder in pubspec.yaml:
assets:
- assets/images/
Ok, so I've read somewhere that the asset file can be accessed like this:
import 'package:flutter/services.dart' show rootBundle;
final byteData = await rootBundle.load('assets/images/myImage.png');
But I don't know how to convert byteData to a File object that represents the actual file.
I think I'm missing something very basic here. Or maybe is there is a proper way to do this that has nothing to do with this approach?
Please help.
Thanks in advance!
If you want to write a file on a user device you should look here: https://flutter.dev/docs/cookbook/persistence/reading-writing-files
Shared preferences are a space in a phone where you app can write, so it's exactly what you want!
Assets are part of you app and are not meant to be modified within the app.
During a build, Flutter places assets into a special archive called
the asset bundle that apps read from at runtime. According to the flutter website
Hope this helps!

Saving files locally so available to email or view in file manager Android

Flutter, dart and Visual Studio. Android Devices.
After saving a file and reading it back to ensure all went OK I can't find the file, so it can't be emailed or viewed at all.
How can I save it so the user can see the file, so they can read it, or email it etc.
Thanks
class SaveJson {
SaveJson();
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Future<File> get _localFile async {
final path = await _localPath;
final file = File('${path}/macf.txt');
return file;
}
Future<File> writeJson(String data) async {
final file = await _localFile;
return file.writeAsString(data);
}
read() async {
try {
final directory = await getApplicationDocumentsDirectory();
final file = File('${directory.path}/macf.txt');
String text = await file.readAsString();
print(text);
} catch (e) {
print("Couldn't read file");
}
}
}
You are using the path_provider package and The getApplicationDocumentsDirectory returns the path to the applications hidden directory. Users can't see this directory with file managers (There is a way to find it but that is not easy for end user).
You can use the downloads_path_provider package:
import 'package:downloads_path_provider/downloads_path_provider.dart';
Future<Directory> downloadsDirectory = DownloadsPathProvider.downloadsDirectory;
In this code, the downloadsDirectory is the Downloads directory in phone storage, that can be seen by user. Then you can open or email it.
downloads_path_provider package link

How open files on Windows Phone 8?

In my app I download several kinds of files (like audio,video,pdf,powerpoint,ect) .
So I receive those data from the webserver as byte[] objects.
So I would like to open them with a video player or a pdfreader now.
What am I supposed to do?
I tried this code but I guess it only works if ou have a file stored in your project's folder(that's not my case)...doesn't it?
// Access the file.
StorageFile pdfFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync("FileToRead.pdf");
// Launch the pdf file.
await Windows.System.Launcher.LaunchFileAsync(pdfFile);
Use this to get a file from Isolated Storage
var file = await ApplicationData.Current.LocalFolder.GetFileAsync(filename);

Resources