flutterdartpdfflutter-dependencies

Generate PDF button is not working on Flutter


I'm working on a Flutter application where I need to generate a PDF when a button is pressed. I use package:pdf/pdf.dart. However, the "Generate PDF" button is not functioning as expected. I'm encountering the following error in the console:

this is my error console :

E/flutter ( 7975): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: RangeError (index): Index out of range: no indices are valid: 0 E/flutter ( 7975): #0 Uint8List.[] (dart:typed_data-patch/typed_data_patch.dart:2271:7) E/flutter ( 7975): #1 InputBuffer.[] (package:image/src/util/input_buffer.dart:44:39) E/flutter ( 7975): #2 JpegData.validate (package:image/src/formats/jpeg/jpeg_data.dart:64:17) E/flutter ( 7975): #3 JpegDecoder.isValidFile (package:image/src/formats/jpeg_decoder.dart:18:50) E/flutter ( 7975): #4 findDecoderForData (package:image/src/formats/formats.dart:116:11) E/flutter ( 7975): #5 new MemoryImage (package:pdf/src/widgets/image_provider.dart:101:24) E/flutter ( 7975): #6 CetakinvoicePage._generatePDF. (package:smta/cetakinvoicepage.dart:421:22) E/flutter ( 7975): #7 Page.postProcess (package:pdf/src/widgets/page.dart:142:21) E/flutter ( 7975): #8
Document.save (package:pdf/src/widgets/document.dart:130:14) E/flutter ( 7975): #9 CetakinvoicePage._generatePDF (package:smta/cetakinvoicepage.dart:442:39) E/flutter ( 7975): E/flutter ( 7975):

this is my code :

import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:path_provider/path_provider.dart';
import 'package:open_file/open_file.dart';
import 'package:flutter/services.dart' show rootBundle;

class CetakinvoicePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: SafeArea(
          child: SingleChildScrollView(
            child: Column(
              children: [
                // Your existing content here...
                Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Padding(
                        padding: EdgeInsets.symmetric(horizontal: 20.0),
                        child: Column(
                            crossAxisAlignment: CrossAxisAlignment.center,
                            children: [
                              SizedBox(height: 10.0,),
                              Padding(
                                padding: EdgeInsets.symmetric(horizontal: 10.0),
                                child: Row(
                                  children: [
                                    Image.asset(
                                      'assets/images/logosgntulisan.png',
                                      width: 120,
                                    ),
                                    Spacer(),
                                    Column(
                                      children: [
                                        Image.asset(
                                          'assets/images/barcodedummy.png',
                                          width: 150,
                                        ),
                                        SizedBox(height: 5.0,),
                                        const Text(
                                          'SG10202312060001',
                                          style: TextStyle(
                                            fontSize: 16,
                                            color: Colors.black,
                                            fontWeight: FontWeight.w400,
                                          ),
                                        ),
                                      ],
                                    ),
                                  ],
                                ),
                              ),
                              Padding(
                                padding: EdgeInsets.symmetric(horizontal: 5.0),
                                child: Container(
                                  width: double.infinity,
                                  child: const Divider(
                                    color: Colors.black,
                                    thickness: 1.0,
                                  ),
                                ),
                              ),
                              Column(
                                children: [
                                  const Text(
                                    'PT SINERGI GULA NUSANTARA',
                                    style: TextStyle(
                                      fontSize: 16,
                                      color: Colors.black,
                                      fontWeight: FontWeight.w500,
                                    ),
                                  ),
                                ],
                              ),
                            ]
                        ),
                      ),
                    ]
                ),
                // Button to trigger PDF generation
                SizedBox(height: 10.0,),
                ElevatedButton(
                  onPressed: () {
                    _generatePDF(context);
                  },
                  child: Text('Generate PDF'),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  // Function to generate PDF
  Future<void> _generatePDF(BuildContext context) async {
    final pdf = pw.Document();


    // Add content to the PDF
    pdf.addPage(pw.Page(
      pageFormat: PdfPageFormat.a4,
      build: (pw.Context context) {
        return pw.Row(
          children: [
            pw.Column(
              crossAxisAlignment: pw.CrossAxisAlignment.start,
              children: [
              ],
            ),
            pw.Column(
              crossAxisAlignment: pw.CrossAxisAlignment.start,
              mainAxisAlignment: pw.MainAxisAlignment.end,
              children: [
                pw.Text(
                  'Waktu Masuk',
                  style: pw.TextStyle(
                    fontSize: 14,
                    color: PdfColors.black,
                    fontWeight: pw.FontWeight.bold,
                  ),
                ),
                pw.SizedBox(height: 5.0),
                pw.Text(
                  '14-12/2023 19.00',
                  style: pw.TextStyle(
                    fontSize: 14,
                    color: PdfColors.black,
                    fontWeight: pw.FontWeight.normal,
                  ),
                ),
                pw.SizedBox(height: 10.0),
                pw.Image(
                  pw.MemoryImage(
                    // Convert your image to bytes (you might need to change this part)
                    // For example: (await rootBundle.load('assets/images/truktebugambar.jpg')).buffer.asUint8List()
                    Uint8List.fromList([/* your image bytes go here */]),
                  ),
                  height: 100,
                  width: 120,
                ),
                pw.SizedBox(height: 20.0),
              ],
            ),
          ],
        );
      },
    ));

    // Get the application documents directory
    final directory = await getApplicationDocumentsDirectory();

    // Create the PDF file
    final file = File('${directory.path}/example.pdf');
    await file.writeAsBytes(await pdf.save());

    // Open the PDF using a PDF viewer
    OpenFile.open(file.path);
  }
}

I have tried to address this issue by including the necessary code for generating the PDF, but it seems there's an error related to the MemoryImage. I suspect it's related to loading the image for the PDF, but I'm unsure how to resolve it.

Any help or guidance on fixing this issue would be greatly appreciated.


Solution

  • Your error message seems to refer to a Memory Image (probably the one you're trying to create in your pdf method without any parameter). See the comment in your code block saying :

    /* your image bytes go here */

    Try commenting your pw.Image() block until you put something in the Uint8List.fromList(), or change your pw.MemoryImage for something like this :

    pw.MemoryImage(
          (await rootBundle.load('images/mylogo.webp'))
              .buffer
              .asUint8List(),
        )