flutterpdfdartflutter-dependencies

How to load and present a PDF file from the web in Flutter


I'm trying to fetch a PDF file from a URL, and to present it in my Flutter app (for both Android and iOS).

I've searched the web and SO for answers on how to present a fetched PDF file in Flutter, but all I could find was how to present a locally pre-added PDF file.

I've also searched for packages doing the same, but I couldn't find one that worked.


Example:

I'm trying to fetch this PDF file for example, and to present it inside a Flutter widget screen in my app.

Does anyone know how can I achieve that?

Thank you!


Solution

  • Use flutter_pdfview package.

    1. Add Permission in android manifest
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    
    1. Add the dependencies in pubspec.yaml
    dependencies:
      flutter:
        sdk: flutter
      flutter_pdfview: ^1.0.1
      http: ^0.12.0+4
      path_provider: any
      permission_handler: 4.4.0 //For asking permission to load the pdf
    
    1. Then use the PDFView

    Full Code:

    import 'package:flutter/material.dart';
    import 'package:flutter_pdfview/flutter_pdfview.dart';
    import 'dart:io';
    import 'package:http/http.dart' as http;
    import 'package:path_provider/path_provider.dart';
    import 'package:permission_handler/permission_handler.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      String urlPDFPath = "";
      bool exists = true;
      int _totalPages = 0;
      int _currentPage = 0;
      bool pdfReady = false;
      PDFViewController _pdfViewController;
      bool loaded = false;
    
      Future<File> getFileFromUrl(String url, {name}) async {
        var fileName = 'testonline';
        if (name != null) {
          fileName = name;
        }
        try {
          var data = await http.get(url);
          var bytes = data.bodyBytes;
          var dir = await getApplicationDocumentsDirectory();
          File file = File("${dir.path}/" + fileName + ".pdf");
          print(dir.path);
          File urlFile = await file.writeAsBytes(bytes);
          return urlFile;
        } catch (e) {
          throw Exception("Error opening url file");
        }
      }
    
      void requestPersmission() async {
        await PermissionHandler().requestPermissions([PermissionGroup.storage]);
      }
    
      @override
      void initState() {
        requestPersmission();
        getFileFromUrl("http://www.africau.edu/images/default/sample.pdf").then(
          (value) => {
            setState(() {
              if (value != null) {
                urlPDFPath = value.path;
                loaded = true;
                exists = true;
              } else {
                exists = false;
              }
            })
          },
        );
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        print(urlPDFPath);
        if (loaded) {
          return Scaffold(
            body: PDFView(
              filePath: urlPDFPath,
              autoSpacing: true,
              enableSwipe: true,
              pageSnap: true,
              swipeHorizontal: true,
              nightMode: false,
              onError: (e) {
                //Show some error message or UI
              },
              onRender: (_pages) {
                setState(() {
                  _totalPages = _pages;
                  pdfReady = true;
                });
              },
              onViewCreated: (PDFViewController vc) {
                setState(() {
                  _pdfViewController = vc;
                });
              },
              onPageChanged: (int page, int total) {
                setState(() {
                  _currentPage = page;
                });
              },
              onPageError: (page, e) {},
            ),
            floatingActionButton: Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: <Widget>[
                IconButton(
                  icon: Icon(Icons.chevron_left),
                  iconSize: 50,
                  color: Colors.black,
                  onPressed: () {
                    setState(() {
                      if (_currentPage > 0) {
                        _currentPage--;
                        _pdfViewController.setPage(_currentPage);
                      }
                    });
                  },
                ),
                Text(
                  "${_currentPage + 1}/$_totalPages",
                  style: TextStyle(color: Colors.black, fontSize: 20),
                ),
                IconButton(
                  icon: Icon(Icons.chevron_right),
                  iconSize: 50,
                  color: Colors.black,
                  onPressed: () {
                    setState(() {
                      if (_currentPage < _totalPages - 1) {
                        _currentPage++;
                        _pdfViewController.setPage(_currentPage);
                      }
                    });
                  },
                ),
              ],
            ),
          );
        } else {
          if (exists) {
            //Replace with your loading UI
            return Scaffold(
              appBar: AppBar(
                title: Text("Demo"),
              ),
              body: Text(
                "Loading..",
                style: TextStyle(fontSize: 20),
              ),
            );
          } else {
            //Replace Error UI
            return Scaffold(
              appBar: AppBar(
                title: Text("Demo"),
              ),
              body: Text(
                "PDF Not Available",
                style: TextStyle(fontSize: 20),
              ),
            );
          }
        }
      }
    }