fdevs_web_processor

A Flutter plugin for rendering HTML to PDF on Android.

pub package

Features

  • HTML to PDF — Convert any HTML string into a PDF document.
  • Continuous mode — Generate single-page, dynamically-sized PDFs perfect for thermal receipts and long invoices.
  • Paginated mode — Fixed page sizes ideal for A4 documents, letters, and reports.
  • Built-in page sizes — Quick presets for a4, a5, letter, legal, mm80, and mm58 thermal rolls.
  • Configurable margins — Control margins in PDF points (1/72 inch).
  • Asset loading — Automatically waits for images, stylesheets, and fonts with a configurable timeout.
  • Post-load script — Inject custom JavaScript to modify the DOM before capture.
  • Typed exceptions — Clear, actionable error messages for every failure mode.

Platform Support

Android iOS
  • Android: API 19+ (fully implemented)
  • iOS: Planned for a future release

Installation

flutter pub add fdevs_web_processor

Usage

Basic example — A4 invoice

import 'dart:io';
import 'dart:typed_data';
import 'package:fdevs_web_processor/fdevs_web_processor.dart';

Future<void> generateInvoice() async {
  final html = '''
    <html>
      <body style="font-family: Arial; padding: 40px;">
        <h1>Invoice #001</h1>
        <p>Total: \$100.00</p>
      </body>
    </html>
  ''';

  final Uint8List pdf = await FdevsWebProcessor.renderToPdf(
    html: html,
    config: const RenderConfig(
      width: PageSize.a4.width,
      height: PageSize.a4.height,
      margins: RenderMargins.all(36), // 0.5 inch margins
    ),
  );

  await File('invoice.pdf').writeAsBytes(pdf);
}

Thermal receipt — 80mm continuous

Future<void> generateReceipt() async {
  final html = '''
    <html>
      <body style="font-family: monospace; font-size: 12px;">
        <h2>MY STORE</h2>
        <p>Item 1 .............. \$10.00</p>
        <p>Item 2 .............. \$15.50</p>
        <hr/>
        <p><strong>Total: \$25.50</strong></p>
        <p>Thank you!</p>
      </body>
    </html>
  ''';

  final Uint8List pdf = await FdevsWebProcessor.renderToPdf(
    html: html,
    config: const RenderConfig(
      width: PageSize.mm80.width, // 80mm roll width
      continuousMode: true,       // Single continuous page
      margins: RenderMargins.symmetric(horizontal: 5),
    ),
  );

  await File('receipt.pdf').writeAsBytes(pdf);
}

API Reference

FdevsWebProcessor.renderToPdf

static Future<Uint8List> renderToPdf({
  required String html,
  RenderConfig config = const RenderConfig(),
});

Renders the given html to a PDF document using the specified config.

Throws:

  • InvalidInputException — HTML is empty or config is invalid.
  • WebViewException — WebView initialization or load failure.
  • AssetTimeoutException — Assets failed to load in time.
  • PdfExportException — PDF generation failed.
  • ContentTooLargeException — Content exceeds the maximum renderable height.

RenderConfig

const RenderConfig({
  double? width,              // Output width in PDF points
  double? height,             // Output height in PDF points
  RenderMargins margins,      // Page margins
  double devicePixelRatio,    // Reserved for future use (default: 2.0)
  int assetLoadTimeoutMs,     // Max time to wait for assets (default: 10000)
  bool continuousMode,        // Single continuous page (default: false)
  String? baseUrl,            // Base URL for relative assets
  String? postLoadScript,     // JS to run before capture
});

PageSize presets

Preset Dimensions Use case
PageSize.a4 595 × 842 pt Standard documents
PageSize.a5 420 × 595 pt Small documents
PageSize.letter 612 × 792 pt US documents
PageSize.legal 612 × 1008 pt Legal documents
PageSize.mm80 226 pt width, auto height 80mm thermal receipts
PageSize.mm58 164 pt width, auto height 58mm thermal receipts

Error Handling

All errors are thrown as subclasses of RenderException:

try {
  final pdf = await FdevsWebProcessor.renderToPdf(html: html);
} on ContentTooLargeException catch (e) {
  // Content too tall — consider splitting into multiple documents
  print('Content height: ${e.contentHeightPx}px (max: ${e.maxHeightPx}px)');
} on RenderException catch (e) {
  // All other rendering errors
  print('Error [${e.code}]: ${e.message}');
}

Android Permissions

The plugin requires the INTERNET permission to load external images, fonts, and stylesheets. This is already declared in the plugin's AndroidManifest.xml, so no additional setup is needed.

Testing

Unit tests

flutter test

Android integration tests

Integration tests run on a real device or emulator via the example app:

./tool/run_android_integration_test.sh

Or manually:

cd example
flutter test integration_test/plugin_integration_test.dart -d <device-id>

Additional information

For more help getting started with Flutter, view the online documentation, which offers tutorials, samples, guidance on mobile development, and a full API reference.