TL;DR: Want to open and save PDF files locally in your Flutter app? Let’s easily do it with Syncfusion Flutter PDF Viewer. This blog covers creating a Flutter app, adding dependency packages, and implementing functions to load and save PDFs with PDF Viewer and File Picker.
Opening and viewing PDF files from a local device’s storage offers several benefits, such as faster access to the files and enhanced privacy and security by viewing sensitive files within that device.
Syncfusion Flutter PDF Viewer widget lets you view PDF documents seamlessly and efficiently on the Android, iOS, web, Windows, and macOS platforms. It has highly interactive and customizable features such as magnification, virtual bi-directional scrolling, page navigation, text selection, text search, page layout options, document link navigation, bookmark navigation, form filling, and reviewing with text markup annotations.
In this blog, we’ll see how to load and save PDF files from and to a local device’s storage using Syncfusion Flutter PDF Viewer and File Picker.
Create a Flutter app and add dependencies
First, create a new Flutter app and add the following dart packages as dependencies in it:
- syncfusion_flutter_pdfviewer
- File_picker
dependencies:
flutter:
sdk: flutter
file_picker: ^X.X.X
syncfusion_flutter_pdfviewer: ^X.X.X
Note: The X.X.X denotes the version of the packages.
After adding the dependencies, import the packages into your dart code.
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
import 'package:file_picker/file_picker.dart';
Open local PDF files
Create the PdfViewer (widget) and PdfViewerState classes to build and display the chosen PDF file in the Syncfusion Flutter PDF Viewer( SfPdfViewer ). Then, in the AppBar method, configure the Open and Save buttons to open and save PDF files with the help of File Picker.
Refer to the following code example.
class PdfViewer extends StatefulWidget {
const PdfViewer({super.key});
@override
State<PdfViewer> createState() => _PdfViewerState();
}
class _PdfViewerState extends State<PdfViewer> {
final PdfViewerController _pdfViewerController = PdfViewerController();
Uint8List? _pdfBytes;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(onPressed: _openFile, icon: const Icon(Icons.folder_open)),
IconButton(onPressed: _saveFile, icon: const Icon(Icons.save)),
Spacer()
],
),
body: _pdfBytes != null
? SfPdfViewer.memory(
_pdfBytes!,
controller: _pdfViewerController,
)
: const Center(
child: Text(
'Choose a PDF file to open',
)),
);
}
}
Now, let’s define the _openFile function to browse and choose a PDF file from the local storage with the help of File Picker. This function will be invoked in the onPressed callback for the Open button. Then, assign the file stream to the SfPdfViewer.
Refer to the following code example.
/// Open a PDF file from the local device's storage.
Future<void> _openFile() async {
FilePickerResult? filePickerResult = await FilePicker.platform
.pickFiles(type: FileType.custom, allowedExtensions: ['pdf']);
if (filePickerResult != null) {
if (kIsWeb) {
_pdfBytes = filePickerResult.files.single.bytes;
} else {
_pdfBytes =
await File(filePickerResult.files.single.path!).readAsBytes();
}
}
setState(() {});
}
Save PDF files to local storage
To save the modified PDF files to local storage, we use SfPdfViewer’s SaveDocument method to obtain the modified PDF file stream and then pass it to the FilePicker widget to write it to the desired location.
This blog example shows how to save PDF files on the web and other platforms (Android, iOS, macOS, and Windows). On the web platform, the file will be downloaded in the browser when pressing the Save button, whereas on other platforms, we will be allowed to choose the folder directory in which we wish to save the file.
Let’s now create two SaveHelper classes for the web and other platforms to perform the above-mentioned actions.
Save on web platform
import 'dart:convert';
import 'dart:html';
class SaveHelper {
static Future<void> save(List<int> bytes, String fileName) async {
AnchorElement(
href:
'data:application/octet-stream;charset=utf-16le;base64,${base64.encode(bytes)}')
..setAttribute('download', fileName)
..click();
}
}
Save on Android, iOS, macOS, and Windows
import 'dart:io';
import 'package:file_picker/file_picker.dart';
class SaveHelper {
static Future<void> save(List<int> bytes, String fileName) async {
String? directory = await FilePicker.platform.getDirectoryPath();
if (directory != null) {
final File file = File('$directory/$fileName');
if (file.existsSync()) {
await file.delete();
}
await file.writeAsBytes(bytes);
}
}
}
Note: Before proceeding to the next step, please ensure that the created SaveHelper class files are imported into the main dart file.
Finally, let’s define the _saveFile function in your widget’s build method, where we can call the SaveHelper.save() method to save a PDF file to the local storage. And this _saveFile function will be invoked in the onPressed callback for the Save button.
Refer to the following code example.
/// Save a PDF file to the desired local device's storage location.
Future<void> _saveFile() async {
if (_pdfViewerController.pageCount > 0) {
List<int> bytes = await _pdfViewerController.saveDocument();
SaveHelper.save(bytes, 'Saved.pdf');
}
}
Execute the application with the above code examples, and you will get the output for the Android platform, as shown in the following image .
GitHub reference
For more details, refer to the Open and save PDF files from and to local device’s storage in the Flutter GitHub demo.
Conclusion
Thanks for reading! I hope you now have a clear idea about how to open and save PDF files from and to local device storage using the Flutter PDF Viewer. Try this in your application and share your feedback in the comments below.
The new version of Essential Studio is available on the License and Downloads page for current customers. If you are not a Syncfusion customer, try our 30-day free trial to check out our newest features.
You can share your feedback and questions through the comments section below or contact us through our support forums, support portal, or feedback portal. We are always happy to assist you!