Hello I have this method that gets pdf from api and returns decoded file, I am able to display it on click, but i want to save it to device. Here is my method for decoding pdf:
Future<File> _storeFile(String bytes) async {
final filename = "${_dokument?.naziv}";
final bytes = _dokument?.bytes;
Uint8List base64Decode(String source) => base64.decode(source);
await checkDocumentFolder();
String dir = directory!.path;
//final file = File('${dir.path}/$filename');
final file = File('$dir/$filename');
//var pdfBytes = bytes?.split(",")[1];
if (!file.existsSync()) file.create();
var pdfBytes = bytes?.substring(bytes.indexOf(",") 1);
print(pdfBytes);
await file.writeAsBytes(base64Decode(pdfBytes!), flush: true);
return file;
}
So my question is, can i somehow save file returned from this method to mobile device.
CodePudding user response:
yes you can store your file in device i suggest you to see this article and this
also you can use file_saver package to store file all platform flutter support
CodePudding user response:
Please try this
downloadFile(var filePath, var documentUrl) async {
try {
/// setting filename
final filename = filePath;
String dir = (await getApplicationDocumentsDirectory()).path;
if (await File('$dir/$filename').exists()) return File('$dir/$filename');
String url = documentUrl;
/// requesting http to get url
var request = await HttpClient().getUrl(Uri.parse(url));
/// closing request and getting response
var response = await request.close();
/// getting response data in bytes
var bytes = await consolidateHttpClientResponseBytes(response);
/// generating a local system file with name as 'filename' and path as '$dir/$filename'
File file = new File('$dir/$filename');
/// writing bytes data of response in the file.
await file.writeAsBytes(bytes);
return file;
}
catch (err) {
print(err);
}
}
CodePudding user response:
There are a few things to consider.
Saving a file differs on various devices. In the case of PDF files, I assume that you want them to be easily accessible to the user. To make it happen, it can't be stored in the application's files - it would require a lot of digging to find the file by the user himself.
It also requires several permissions, some of which are configured directly in platform-specific files and some have to be requested from the user in runtime. Permission Handler package comes in handy for this job.
So, here is how to implement it:
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
iOS
Future<void> saveFile(String fileName) async {
var file = File('');
// Platform.isIOS comes from dart:io
if (Platform.isIOS) {
final dir = await getApplicationDocumentsDirectory();
file = File('${dir.path}/$fileName');
}
To make it work on iOS you have to add 2 keys to ios/Runner/Info.plist
file.
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>
Android
if (Platform.isAndroid) {
var status = await Permission.storage.status;
if (status != PermissionStatus.granted) {
status = await Permission.storage.request();
}
if (status.isGranted) {
const downloadsFolderPath = '/storage/emulated/0/Download/';
Directory dir = Directory(downloadsFolderPath);
file = File('${dir.path}/$fileName');
}
}
For Android, on the other hand, you'll have to do a few more things.
At first, it is required to set proper compileSdkVersion
in android/app/build.gradle
file. As I'm writing this - it should be set to 33
.
Also 2 lines are needed in android/app/src/main/AndroidManifest.xml
, right below manifest
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
And of course, as it can be seen in the code - we also need to request a permission from a user.
Writing to the file
// load file that you want to save on user's phone
// it can be loaded from whenever you want, e.g. some API.
final byteData = await rootBundle.load('assets/$fileName');
try {
await file.writeAsBytes(byteData.buffer
.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
} on FileSystemException catch (err) {
// handle error
}
}
File Saver package saves files to the application's data, so it won't be so easy to find for the user. It is also published by an unverified uploader so I'd definitely keep it in mind.