MegaPDF Flutter Plugin

A Flutter plugin for interacting with the MegaPDF API to manipulate PDF files with features like conversion, compression, merging, splitting, protection, and more.

Features

  • PDF Conversion: Convert PDFs to other formats (DOCX, XLSX, PPTX, HTML, TXT, JPG, PNG) and vice versa
  • PDF Compression: Reduce PDF file size
  • PDF Merging: Combine multiple PDFs into a single document
  • PDF Splitting: Split a PDF into multiple documents
  • PDF Protection: Add password protection to PDFs
  • PDF Unlocking: Remove password protection from PDFs
  • PDF Watermarking: Add text or image watermarks to PDFs
  • PDF Rotation: Rotate pages in a PDF
  • OCR Processing: Extract text from PDFs or make them searchable
  • Digital Signatures: Add electronic signatures to PDFs
  • Page Numbers: Add page numbers to PDFs
  • PDF Chat: Ask questions about PDF content and get answers
  • Remove Pages: Remove specific pages from a PDF

Getting Started

Installation

Add this to your package's pubspec.yaml file:

dependencies:
  megapdf_flutter: ^0.1.0

Initialization

To use the plugin, you need to initialize it with your MegaPDF API key:

import 'package:megapdf_flutter/megapdf_flutter.dart';

final megaPdf = MegaPdf();

void initializeSdk() async {
  await megaPdf.initialize(apiKey: 'your_api_key');
  // Now you can use the SDK
}

The plugin will store your API key in shared preferences for future use, so you can also try to initialize from saved preferences:

final initialized = await megaPdf.initializeFromPreferences();
if (initialized) {
  // SDK is initialized with the saved API key
} else {
  // Need to initialize with a new API key
}

Usage Examples

Convert PDF to DOCX

import 'dart:io';
import 'package:megapdf_flutter/megapdf_flutter.dart';

Future<void> convertPdfToDocx(File pdfFile) async {
  final megaPdf = MegaPdf();
  await megaPdf.initialize(apiKey: 'your_api_key');

  final response = await megaPdf.convertPdf(
    file: pdfFile,
    outputFormat: 'docx',
    options: ConversionOptions(
      ocr: true, // Enable OCR for better text extraction
    ),
  );

  if (response.success) {
    print('Conversion successful!');
    print('File URL: ${response.fileUrl}');
    print('Filename: ${response.filename}');
  } else {
    print('Conversion failed: ${response.error}');
  }
}

Compress PDF

Future<void> compressPdf(File pdfFile) async {
  final response = await megaPdf.compressPdf(
    file: pdfFile,
    options: CompressionOptions(
      quality: 'medium', // 'low', 'medium', or 'high'
    ),
  );

  if (response.success) {
    print('Compression successful!');
    print('Original size: ${response.get<int>('originalSize')} bytes');
    print('Compressed size: ${response.get<int>('compressedSize')} bytes');
    print('Compression ratio: ${response.get<String>('compressionRatio')}');
  }
}

Merge PDFs

Future<void> mergePdfs(List<File> pdfFiles) async {
  final response = await megaPdf.mergePdfs(
    files: pdfFiles,
    order: [2, 0, 1], // Optional: specify custom order (zero-based index)
  );

  if (response.success) {
    print('Merge successful!');
    print('Merged file URL: ${response.fileUrl}');
  }
}

Split PDF

// Split by page ranges
Future<void> splitByRanges(File pdfFile) async {
  final response = await megaPdf.splitPdf(
    file: pdfFile,
    splitMethod: 'range',
    pageRanges: '1-3,5,7-9', // Page numbers start from 1
  );

  if (response.success) {
    if (response.get<bool>('isLargeJob') == true) {
      // For large jobs, get the status
      final jobId = response.get<String>('jobId');
      final statusResponse = await megaPdf.getSplitStatus(jobId: jobId);
      print('Split job status: ${statusResponse.get<String>('status')}');
    } else {
      // For smaller jobs, results are returned immediately
      final splitParts = response.get<List>('splitParts');
      print('Split into ${splitParts?.length} parts');
    }
  }
}

// Split every N pages
Future<void> splitEveryNPages(File pdfFile) async {
  final response = await megaPdf.splitPdf(
    file: pdfFile,
    splitMethod: 'every',
    everyNPages: 2, // Split every 2 pages
  );
}

// Extract each page to a separate PDF
Future<void> extractEachPage(File pdfFile) async {
  final response = await megaPdf.splitPdf(
    file: pdfFile,
    splitMethod: 'extract',
  );
}

Protect PDF with Password

Future<void> protectPdf(File pdfFile) async {
  final response = await megaPdf.protectPdf(
    file: pdfFile,
    password: 'your_password',
    options: ProtectionOptions(
      permission: 'restricted', // 'restricted' or 'all'
      allowPrinting: true,
      allowCopying: false,
      allowEditing: false,
    ),
  );

  if (response.success) {
    print('PDF protected successfully!');
  }
}

Check if PDF is Password Protected

Future<void> checkPasswordProtection(File pdfFile) async {
  final response = await megaPdf.checkPasswordProtection(file: pdfFile);

  if (response.success) {
    final isProtected = response.get<bool>('isPasswordProtected');
    print('Is PDF password protected? ${isProtected ? 'Yes' : 'No'}');
  }
}

Unlock Password-Protected PDF

Future<void> unlockPdf(File pdfFile) async {
  final response = await megaPdf.unlockPdf(
    file: pdfFile,
    password: 'your_password',
  );

  if (response.success) {
    print('PDF unlocked successfully!');
  }
}

Add Watermark to PDF

// Text watermark
Future<void> addTextWatermark(File pdfFile) async {
  final response = await megaPdf.watermarkPdf(
    file: pdfFile,
    options: WatermarkOptions(
      watermarkType: 'text',
      text: 'CONFIDENTIAL',
      textColor: '#FF0000',
      fontSize: 48,
      fontFamily: 'Helvetica',
      opacity: 30, // 0-100
      rotation: 45,
      position: 'center', // 'center', 'top-left', 'top-right', 'bottom-left', 'bottom-right', 'tile'
      pages: 'all', // 'all', 'odd', 'even', 'custom'
    ),
  );

  if (response.success) {
    print('Watermark added successfully!');
  }
}

// Image watermark
Future<void> addImageWatermark(File pdfFile, File watermarkImage) async {
  final response = await megaPdf.watermarkPdf(
    file: pdfFile,
    options: WatermarkOptions(
      watermarkType: 'image',
      watermarkImage: watermarkImage,
      scale: 50, // 0-100
      opacity: 30, // 0-100
      rotation: 0,
      position: 'center',
    ),
  );
}

Rotate PDF Pages

Future<void> rotatePdfPages(File pdfFile) async {
  final response = await megaPdf.rotatePdf(
    file: pdfFile,
    rotations: [
      PageRotation(pageNumber: 1, angle: 90),
      PageRotation(pageNumber: 2, angle: 180),
      PageRotation(pageNumber: 4, angle: 270),
    ],
  );

  if (response.success) {
    print('PDF pages rotated successfully!');
  }
}

OCR: Extract Text from PDF

Future<void> extractTextWithOcr(File pdfFile) async {
  final response = await megaPdf.extractTextOcr(
    file: pdfFile,
    options: OcrOptions(
      language: 'eng', // Language code (e.g., 'eng', 'fra', 'deu')
      preserveLayout: true,
      pageRange: 'all', // 'all', 'specific'
      pages: '1-3,5', // Used if pageRange is 'specific'
    ),
  );

  if (response.success) {
    final extractedText = response.get<String>('text');
    print('Extracted text: $extractedText');
  }
}

Make PDF Searchable with OCR

Future<void> makeSearchablePdf(File pdfFile) async {
  final response = await megaPdf.makeSearchablePdf(
    file: pdfFile,
    options: OcrOptions(
      language: 'eng',
    ),
  );

  if (response.success) {
    print('PDF is now searchable!');
    print('Searchable PDF URL: ${response.fileUrl}');
  }
}

Add Electronic Signatures to PDF

Future<void> signPdf(File pdfFile) async {
  final response = await megaPdf.signPdf(
    file: pdfFile,
    elements: [
      // Add a signature image
      SignatureElement(
        id: 'signature1',
        type: 'signature',
        position: {'x': 100, 'y': 200},
        size: {'width': 200, 'height': 50},
        data: 'data:image/png;base64,...', // Base64 encoded image data
        page: 0, // First page (zero-based)
      ),

      // Add text
      SignatureElement(
        id: 'text1',
        type: 'text',
        position: {'x': 100, 'y': 300},
        size: {'width': 200, 'height': 30},
        data: 'Signed by John Doe',
        color: '#000000',
        fontSize: 12,
        fontFamily: 'Helvetica',
        page: 0,
      ),

      // Add date
      SignatureElement(
        id: 'date1',
        type: 'date',
        position: {'x': 100, 'y': 350},
        size: {'width': 200, 'height': 30},
        data: '', // Will be filled with current date
        color: '#000000',
        fontSize: 12,
        fontFamily: 'Helvetica',
        page: 0,
      ),
    ],
    performOcr: true, // Make the PDF searchable after signing
    ocrLanguage: 'eng',
  );

  if (response.success) {
    print('PDF signed successfully!');
    print('Signed PDF URL: ${response.fileUrl}');
  }
}

Add Page Numbers to PDF

Future<void> addPageNumbers(File pdfFile) async {
  final response = await megaPdf.addPageNumbers(
    file: pdfFile,
    options: PageNumberOptions(
      format: 'numeric', // 'numeric', 'roman', 'alphabetic'
      position: 'bottom-center', // 'bottom-center', 'bottom-left', 'bottom-right', 'top-center', 'top-left', 'top-right'
      fontFamily: 'Helvetica',
      fontSize: 12,
      color: '#000000',
      startNumber: 1,
      prefix: 'Page ',
      suffix: ' of 10',
      marginX: 40,
      marginY: 30,
      selectedPages: '', // Leave empty for all pages, or use page ranges like '1-3,5,7-9'
      skipFirstPage: true,
    ),
  );

  if (response.success) {
    print('Page numbers added successfully!');
    print('PDF with page numbers URL: ${response.fileUrl}');
  }
}

PDF Chat

// Start a chat with a PDF
Future<void> startPdfChat(File pdfFile) async {
  final response = await megaPdf.startPdfChat(file: pdfFile);

  if (response.success) {
    final sessionId = response.get<String>('sessionId');
    print('Chat session started with ID: $sessionId');

    // Send a message to the chat
    final messageResponse = await megaPdf.sendChatMessage(
      sessionId: sessionId!,
      message: 'What is this document about?',
    );

    if (messageResponse.success) {
      final answer = messageResponse.get<String>('message');
      print('Answer: $answer');
    }

    // Get chat history
    final historyResponse = await megaPdf.getChatHistory(sessionId: sessionId);

    if (historyResponse.success) {
      final messages = historyResponse.get<List>('messages');
      print('Chat history: $messages');
    }

    // Delete the chat session when done
    await megaPdf.deleteChatSession(sessionId: sessionId);
  }
}

Remove Pages from PDF

Future<void> removePages(File pdfFile) async {
  final response = await megaPdf.removePages(
    file: pdfFile,
    pagesToRemove: [2, 4, 6], // Remove pages 2, 4, and 6 (page numbers start from 1)
  );

  if (response.success) {
    print('Pages removed successfully!');
    print('Modified PDF URL: ${response.fileUrl}');
  }
}

API Response Structure

All methods return an ApiResponse object with the following structure:

ApiResponse {
  bool success;           // Whether the request was successful
  int statusCode;         // HTTP status code
  String? error;          // Error message, if any
  dynamic data;           // Response data from the API

  // Helper methods
  T? get<T>(String key);  // Get a specific field from the response data
  String? get fileUrl;    // Get the file URL from the response
  String? get filename;   // Get the filename from the response
  String? get message;    // Get the message from the response
  String? get originalName; // Get the original name from the response
}

Working with Downloaded Files

After processing a PDF, you often need to download and save the resulting file:

// Example of downloading a file after processing
Future<File> downloadAndSaveFile(String fileUrl, String fileName) async {
  final directory = await getApplicationDocumentsDirectory(); // from path_provider package
  final filePath = '${directory.path}/$fileName';

  // If the URL is relative, make it absolute
  if (fileUrl.startsWith('/')) {
    fileUrl = '${megaPdf.baseUrl}$fileUrl';
  }

  // Download the file
  return await megaPdf.downloadFile(fileUrl, filePath);
}

Error Handling

try {
  final response = await megaPdf.compressPdf(file: pdfFile);

  if (response.success) {
    // Handle success
  } else {
    // Handle API-level errors
    print('API error: ${response.error}');
    print('Status code: ${response.statusCode}');
  }
} catch (e) {
  // Handle client-side errors
  print('Client error: $e');
}

Requirements

  • Flutter 3.0.0 or higher
  • Dart 2.17.0 or higher
  • A valid MegaPDF API key (obtain from mega-pdf.com)

Platform Support

  • Android
  • iOS

License

This plugin is released under the MIT License.

Libraries

megapdf_flutter