syncfusion / flutter-widgets

Syncfusion Flutter widgets libraries include high quality UI widgets and file-format packages to help you create rich, high-quality applications for iOS, Android, and web from a single code base.
1.57k stars 771 forks source link

Unable to read FDF file. #1643

Closed GitGud31 closed 7 months ago

GitGud31 commented 9 months ago

I have an FDF file (along with the PDF version of it), I'm following the documentation :

//Loads an existing PDF document.
final PdfDocument document =
    PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());

//Import the FDF into the existing form.
document.form
  .importData(File('Import.fdf').readAsBytesSync(), DataFormat.fdf);

//Save the PDF document.
File('output.pdf').writeAsBytesSync(await document.save());

I'm getting this error:

E/flutter ( 8489): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Invalid argument(s): Incorrect field name.
E/flutter ( 8489): #0      PdfForm._importDataFDF.<anonymous closure> (package:syncfusion_flutter_pdf/src/pdf/implementation/forms/pdf_form.dart:353:11)
E/flutter ( 8489): #1      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:633:13)
E/flutter ( 8489): #2      PdfForm._importDataFDF (package:syncfusion_flutter_pdf/src/pdf/implementation/forms/pdf_form.dart:348:11)

how can I fix this?

karmegams02 commented 9 months ago

The error message “Incorrect field name” is thrown when the data in the FDF file is not associated with the PDF document. If you have any concerns, kindly provide us with the FDF file and PDF document to analyze further in this.

GitGud31 commented 9 months ago

Yes here's the pdf. I used NitroPro 14 to extract the FDF and the XFDF files.

UPDATE

EDIT (added sample code)

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

  @override
  State<DemoSyncfusion> createState() => _DemoSyncfusionState();
}

class _DemoSyncfusionState extends State<DemoSyncfusion> {
  Future<List<int>> _readDocumentData(String name) async {
    final ByteData data = await rootBundle.load('assets/$name');
    return data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
  }

  Future<void> _readPDF() async {
    final logger = Logger();

    final PdfDocument document =
        PdfDocument(inputBytes: await _readDocumentData('cerfa_15497-03.pdf'));

    document.form.importData(
        await _readDocumentData('cerfa_15497-03_data.xfdf'), DataFormat.xfdf);

    logger.d("forms: ${document.form.fields.count}");
    logger.d("first form field: ${document.form.fields[0].name}");

    (document.form.fields[0] as PdfTextBoxField).text = 'zdzdazokdnzadoizndoazinazoinzdzoinzd';
    (document.form.fields[0] as PdfTextBoxField).foreColor = PdfColor.fromCMYK(200, 120, 80, 40);

    List<int> bytes = await document.save();
    document.dispose();
    SaveFile.saveAndLaunchFileMobile(bytes, 'output.pdf');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            TextButton(
              style: ButtonStyle(
                  backgroundColor: MaterialStateProperty.resolveWith(
                      (states) => Colors.blue)),
              onPressed: _readPDF,
              child: const Text(
                'Read PDF',
                style: TextStyle(color: Colors.white),
              ),
            )
          ],
        ),
      ),
    );
  }
}

class SaveFile {
  static Future<void> saveAndLaunchFileMobile(
      List<int> bytes, String fileName) async {
    Directory directory = await getApplicationSupportDirectory();
    String path = directory.path;
    File file = File('$path/$fileName');
    await file.writeAsBytes(bytes, flush: true);
    OpenFile.open('$path/$fileName');
  }
}
irfanajaffer commented 8 months ago

We are currently working to export the PDF into XFDF using nitro PDF. However we can able to export the PDF document using our PDF control and import and modify the form fields.

After filling the form fields in the PDF document, it may appear empty due to the absence of the appearance dictionary. By setting the setDefaultAppearance method in PdfForm class to false, you can create the appearance dictionary. By this, the text will be visible in all PDF Viewers.

The following code sample explains how to set appearance to the PDF form fields.

//Loads an existing PDF document.
final PdfDocument document =
    PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());

//Set the default appearance.
document.form.setDefaultAppearance(true);

//Get the loaded form field and update text.
(document.form.fields[0] as PdfTextBoxField).text = 'Updated';

//Save the PDF document.
File('output.pdf').writeAsBytesSync(await document.save());

In the meantime, We request you to share the exported FDF and the XFDF file to check the reported issue on our end.

AnanthaGokulaRaman commented 7 months ago

The FDF structure created from NitroPro software is not similar to our structure. Due to this reported behavior, we have compared and analyzed our FDF structure with PDF readers (Adobe, Foxit, etc) and confirmed that our FDF creation structures are the same. However, we have logged a feature request to handle this type of FDF data structure. We do not have any immediate plans to implement this feature, but we will include it in any of our upcoming releases.

Please use the feedback link below to track the status of the feature. https://www.syncfusion.com/feedback/51335/add-support-to-import-form-fields-in-all-valid-fdf-formats