flutter_pdfview icon indicating copy to clipboard operation
flutter_pdfview copied to clipboard

PDF not loading on iOS

Open Isuru-Nanayakkara opened this issue 3 years ago • 5 comments

Hi, I'm encountering a strange issue. I've created a widget encapsulating all the functions related to downloading, saving and loading a PDF file. Below is my code.

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_pdfview/flutter_pdfview.dart';
import 'package:http/http.dart' as http;
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';

class PDFViewer extends StatefulWidget {
  final Uri url;

  const PDFViewer({
    Key? key,
    required this.url,
  }) : super(key: key);

  factory PDFViewer.fromRemoteUrl(Uri url) {
    return PDFViewer(url: url);
  }

  factory PDFViewer.fromLocalFile(Uri url) {
    return PDFViewer(url: url);
  }

  @override
  State<PDFViewer> createState() => _PDFViewerState();
}

class _PDFViewerState extends State<PDFViewer> {
  PDFViewController? _pdfViewController;

  @override
  void initState() {
    super.initState();

    _requestStoragePermission();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<File>(
      future: _downloadFileFromUrl(widget.url),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return PDFView(
            filePath: snapshot.data!.path,
            autoSpacing: true,
            enableSwipe: true,
            pageSnap: true,
            swipeHorizontal: false,
            nightMode: false,
            onRender: (int? pages) {
              debugPrint('RENDER $pages');
            },
            onError: (e) {
              //Show some error message or UI
              debugPrint('❌ ERROR: ${e.toString()}');
            },
            onViewCreated: (PDFViewController controller) {
              _pdfViewController = controller;
            },
            onPageChanged: (int? page, int? total) {},
            onPageError: (page, e) {
              debugPrint('❌📃 PAGE ERROR: ${e.toString()}');
            },
          );
        } else {
          return const Center(
            child: CircularProgressIndicator(),
          );
        }
      },
    );
  }

  Future<void> _requestStoragePermission() async {
    Permission.storage.request();
  }

  Future<File> _downloadFileFromUrl(Uri url) async {
    try {
      var response = await http.get(url);
      var bytes = response.bodyBytes;

      var documentDirectory = await getApplicationDocumentsDirectory();
      String fileName = basename(url.path);
      File file = File("${documentDirectory.path}/$fileName");
      File writtenFile = await file.writeAsBytes(bytes);
      return writtenFile;
    } catch (e) {
      throw Exception("Error opening url file");
    }
  }
}

This works fine on Android.

https://user-images.githubusercontent.com/2551877/180832481-4a2270cc-4fb8-42f4-95a0-35692be102be.mp4

However on iOS, the PDF gets downloaded to the documents directory successfully. But it doesn't get loaded on screen. If I move the app to background and then bring it back to foreground, then the PDF gets loaded.

https://user-images.githubusercontent.com/2551877/180832981-de1b8182-1b06-48b7-a0d8-5b050c7b8f85.mp4

Any idea why this might be happening and how to fix this?

Isuru-Nanayakkara avatar Jul 25 '22 16:07 Isuru-Nanayakkara

This issue is present in my implementation as well. I get no error message but the PDF is blank. Did you ever find a workaround or solution to this problem?

charlieforward9 avatar Oct 20 '22 20:10 charlieforward9

@charlieforward9 Unfortunately no. I was doing this as a learning exercise so I didn't pursue further after hitting this roadblock. Sorry.

Isuru-Nanayakkara avatar Oct 24 '22 05:10 Isuru-Nanayakkara

For anyone else who ends up here, I was able to find a workaround by wrapping the PDF generation in a BLOC and using a "retry" button that calls the same function with PDFView widget again.

It seems that the issue is stemming from a function behind the scenes that is returning before the PDF is fully generated, thus an empty slate. Just a theory though, haven't looked BTS at all.

charlieforward9 avatar Oct 28 '22 04:10 charlieforward9

This will help https://www.youtube.com/watch?v=gAUVz0U7eyA

myselfuser1 avatar Mar 17 '23 12:03 myselfuser1