Trouble to generate a pdf in flutter web and then display and download it

39 Views Asked by At

I am building the website where In a section I can generate a pdf from the dynamic values and then to download it to the device.The pdf can be generated and downloaded but not viewed in the browser it returns empty screen. I am using pdf: ^3.10.8(for pdf generating) syncfusion_flutter_pdfviewer: ^20.4.54 (for pdf viewing in web) packages. Most importantly there is no error in the console to resolve. Any help will be appreciated.

I am attaching my screen shots for better understanding

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';

class InvoicePreviewScreen extends StatefulWidget {
  const InvoicePreviewScreen({super.key});

  @override
  State createState() => _InvoicePreviewScreenState();
}

class _InvoicePreviewScreenState extends State<InvoicePreviewScreen> {
  Uint8List? invoiceBytes;

  @override
  void initState() {
    super.initState();
    generateInvoice().then((value) {
      setState(() {
        invoiceBytes = value;
      });
    });
  }

  Future<pw.Font> loadCustomFont() async {
    final fontData = await rootBundle.load("assets/open-sans.ttf");
    return pw.Font.ttf(fontData.buffer.asByteData());
  }

  Future<Uint8List> generateInvoice() async {
    final cusFont = await loadCustomFont();
    final pdf = pw.Document();
    pdf.addPage(
      pw.Page(
        build: (pw.Context context) {
          return pw.Center(
            child: pw.Text("Invoice",
                style: pw.TextStyle(fontSize: 40, font: cusFont)),
          );
        },
      ),
    );
    return pdf.save();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Invoice Preview'),
      ),
      body: Center(
        child: invoiceBytes != null
            ? SfPdfViewer.memory(
                invoiceBytes!,
              )
            : const CircularProgressIndicator(),
      ),
    );
  }
}

This is another way where i can download the pdf but cannot view it

import 'dart:developer';
import 'dart:html' as html;

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';

class PDFSave extends StatefulWidget {
  const PDFSave({super.key});

  @override
  State createState() => _PDFSaveState();
}

class _PDFSaveState extends State<PDFSave> {
  final pdf = pw.Document();
  var anchor;
  String? data;
  Uint8List? pdfInBytes;
  savePDF() async {
    pdfInBytes = await pdf.save();

    log("Save PDF: ${pdfInBytes.toString()}");
    final blob = html.Blob([pdfInBytes], 'application/pdf');
    final url = html.Url.createObjectUrlFromBlob(blob);
    anchor = html.document.createElement('a') as html.AnchorElement
      ..href = url
      ..style.display = 'none'
      ..download = 'pdf.pdf';
    html.document.body?.children.add(anchor);
  }

  createPDF() async {
    final font = await rootBundle.load("assets/open-sans.ttf");
    final ttf = pw.Font.ttf(font);
    pdf.addPage(
      pw.Page(
        build: (pw.Context context) => pw.Column(
          children: [
            pw.Text('Hello World',
                style: pw.TextStyle(fontSize: 40, font: ttf)),
          ],
        ),
      ),
    );

    await savePDF();
    displayPDF();
  }

  displayPDF() {
    log("Display PDF: ${pdfInBytes.toString()}");
    data = Uri.dataFromBytes(
      pdfInBytes!,
      mimeType: 'application/pdf',
    ).toString();
    log("Data Value: ${data.toString()}");
    setState(() {});
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.transparent,
      appBar: AppBar(
        title: const Text('PDF Creator'),
      ),
      body: Column(
        children: [
          data != null
              ? SizedBox(
                  height: 400,
                  width: 300,
                  child: SfPdfViewer.network(
                    data!,
                  ),
                )
              : const CircularProgressIndicator(),
          ElevatedButton(
            child: const Text('Press'),
            onPressed: () {
              anchor.click();
              Navigator.pop(context);
            },
          ),
        ],
      ),
    );
  }
}

PDFSave screen: this is the ui I am getting where the button is working but the view is not this screenshot is associated with the second code format for the PDFSave screen(in the console there is no error)

1

There are 1 best solutions below

0
Aks On

As per the documentation of syncfusion_flutter_pdfviewer

On your web/index.html file, add the following script tags, somewhere in the body of the document:

<script src="//cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.min.js"></script>
<script type="text/javascript">
   pdfjsLib.GlobalWorkerOptions.workerSrc = "//cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.worker.min.js";
</script>