PDF Generation and download

Custom Code

I want to download a complex pdf on my app which takes a series of lists (image and string)
I need the pdf to be structured in a particular way as shown below. there are 9 categories all together for each sections (items you identified correctly, items that you failed to identify correctly and bonus item you identify). the categories are Roofing, HVAC, interior, exterior, plumbing, electric, structure, kitchen and bathroom

What have you tried so far?

I've tried this code

import 'package:pdf/widgets.dart' as pw;

import 'package:pdf/pdf.dart';

import 'package:path_provider/path_provider.dart';

import 'dart:io';

Future<String> generateAndDownloadPDF({

required List<String> roofingImages,

required List<String> roofingDescriptions,

required List<String> exteriorImages,

required List<String> exteriorDescriptions,

required List<String> plumbingImages,

required List<String> plumbingDescriptions,

required List<String> structureImages,

required List<String> structureDescriptions,

required List<String> electricImages,

required List<String> electricDescriptions,

required List<String> hvacImages,

required List<String> hvacDescriptions,

required List<String> kitchenImages,

required List<String> kitchenDescriptions,

required List<String> bathroomImages,

required List<String> bathroomDescriptions,

required List<String> interiorImages,

required List<String> interiorDescriptions,

}) async {

try {

final pdf = pw.Document();

pdf.addPage(

pw.MultiPage(

build: (pw.Context context) => [

pw.Header(level: 0, text: 'Field Exam Results'),

..._buildDynamicSections('Items You Identified Correctly', [

['Roofing', roofingImages, roofingDescriptions],

['Exterior', exteriorImages, exteriorDescriptions],

['Plumbing', plumbingImages, plumbingDescriptions],

['Structure', structureImages, structureDescriptions],

['Electric', electricImages, electricDescriptions],

['HVAC', hvacImages, hvacDescriptions],

['Kitchen', kitchenImages, kitchenDescriptions],

['Bathroom', bathroomImages, bathroomDescriptions],

['Interior', interiorImages, interiorDescriptions],

]),

],

),

);

// Get local directory for saving the file

final directory = await getApplicationDocumentsDirectory();

final filePath = '${directory.path}/FieldExamResult.pdf';

final file = File(filePath);

await file.writeAsBytes(await pdf.save());

// Convert file path to a downloadable URI

final downloadUri = Uri.file(filePath).toString();

return downloadUri; // โœ… Always returns a valid string

} catch (e) {

print('Error generating PDF: $e');

return 'Error generating PDF: $e'; // โœ… Returning an error message instead of null

}

}

// Function to Generate Sections Dynamically

List<pw.Widget> _buildDynamicSections(String title, List<List<dynamic>> sectionData) {

List<pw.Widget> sections = [

pw.SizedBox(height: 20),

pw.Text(title, style: pw.TextStyle(fontWeight: pw.FontWeight.bold, fontSize: 14)),

pw.SizedBox(height: 10),

];

for (var section in sectionData) {

String category = section[0];

List<String> imagePaths = section[1];

List<String> descriptions = section[2];

if (imagePaths.isNotEmpty && descriptions.isNotEmpty) {

sections.add(pw.Text(category, style: pw.TextStyle(fontWeight: pw.FontWeight.bold, fontSize: 12)));

sections.add(_buildSubSection(category, imagePaths, descriptions));

}

}

return sections;

}

// Function to Create Individual Subsections

pw.Widget _buildSubSection(String title, List<String> imagePaths, List<String> descriptions) {

if (imagePaths.isEmpty || descriptions.isEmpty) return pw.Container();

return pw.Column(

crossAxisAlignment: pw.CrossAxisAlignment.start,

children: [

pw.Text(title, style: pw.TextStyle(fontSize: 14, fontWeight: pw.FontWeight.bold)),

pw.SizedBox(height: 5),

pw.Wrap(

spacing: 10,

runSpacing: 10,

alignment: pw.WrapAlignment.start,

children: List.generate(imagePaths.length, (index) => pw.Container(

width: 120,

padding: const pw.EdgeInsets.all(5),

decoration: pw.BoxDecoration(

border: pw.Border.all(color: PdfColors.grey),

borderRadius: pw.BorderRadius.circular(5),

),

child: pw.Column(

crossAxisAlignment: pw.CrossAxisAlignment.center,

children: [

pw.Container(

width: 100,

height: 100,

child: pw.Image(pw.MemoryImage(File(imagePaths[index]).readAsBytesSync())),

),

pw.SizedBox(height: 5),

pw.Text(descriptions[index], textAlign: pw.TextAlign.center, style: pw.TextStyle(fontSize: 10)),

],

),

)),

),

pw.SizedBox(height: 10),

],

);

}


I use all the variables as argument and the return type to be a string which will be a download url

Did you check FlutterFlow's Documentation for this topic?
Yes
2
2 replies