Категория

Круговой обмен данными PDF-формы: экспорт и импорт с помощью JavaScript

2026-09-28 08:35:15 Allen Yang
AI Summarize:
ChatGPT
ChatGPT ✓
Claude ✓
Grok ✓
Perplexity ✓
Quick
Quick
Concise overview
Highlights
Key takeaways
Detailed
Structured explanation
Brief
One sentence summary
Summarize |

Экспортированный файл данных формы XML

Когда форма PDF заполнена, введённые значения сливаются с визуальной компоновкой в единый артефакт. Перенос этих записей в другой шаблон означает повторный ручной ввод каждого поля. Выход — относиться к данным формы как к переносимому ресурсу: извлечь значения полей в отдельный файл данных, а затем подать его обратно в пустой экземпляр формы, чтобы воспроизвести все записи за один автоматический проход. Именно этот цикл «экспорт — импорт» реализует Spire.PDF for JavaScript через PdfFormWidget.ExportData и PdfFormWidget.ImportData.

Оба метода принимают три формата файлов: XML, FDF и XFDF. Переключение между ними — это не более чем изменение значения перечисления DataFormat: способ вызова остаётся тем же, меняется лишь структура выходного файла на диске. Поскольку Spire.PDF for JavaScript полностью работает в браузере на основе WebAssembly, весь цикл выполняется локально через виртуальную файловую систему (VFS), без участия серверной части, и документ никогда не покидает клиент.

В этой статье рассматривается полный поток данных:

Информацию об установке и настройке проекта см. в разделе Интеграция Spire.PDF for JavaScript в проект React. В приведённых ниже примерах предполагается, что Spire.PDF установлен и модуль WebAssembly инициализирован.


Три формата данных форм: краткий обзор

Прежде чем переходить к коду, полезно разобраться в трёх форматах, с которыми работают ExportData и ImportData. Все три несут одну и ту же полезную нагрузку — набор пар «имя поля / значение», — но упаковывают её по-разному. Если выбрать подходящий формат сразу, позже будет меньше сложностей, когда файл данных потребуется передать, проверить или подать в другой инструмент.

Формат Значение перечисления Структура файла Читаемость для человека Лучше всего подходит для
XML DataFormat.Xml XML данных формы Adobe; имя поля становится именем элемента, а значение — содержимым элемента Да Быстрого просмотра, отладки, простых инструментов
FDF DataFormat.Fdf Forms Data Format; текстовая структура, начинающаяся с %FDF-, где /T содержит имя поля, а /V — значение Нет Компактной передачи между программами
XFDF DataFormat.XFdf XFDF, стандартный XML; один <field name="…"> на каждое поле, значение внутри <value> Да Контроля версий, обмена между системами

Все три формата не теряют значения полей — при экспорте и импорте ничего не отбрасывается и не преобразуется. Выбор между ними определяется исключительно удобством рабочего процесса, к чему мы вернёмся в руководстве по выбору формата ниже.


Экспорт данных формы PDF

Первая половина цикла — извлечение. PdfFormWidget.ExportData берёт все значения полей формы и записывает их в один файл данных. Второй аргумент — перечисление DataFormat — определяет, в каком формате будет выполнена запись. Третий аргумент — имя формы; для неименованной AcroForm передайте пустую строку.

В приведённом ниже примере загружается заполненная форма сведений о клиенте, её дескриптор формы оборачивается в PdfFormWidget, а значения полей экспортируются в файл XML. Варианты для FDF и XFDF добавлены в виде закомментированных строк — раскомментируйте любую из них, чтобы сменить формат, не трогая ничего остального:

function App() {
  const exportFormData = async () => {
    // Get the Spire.PDF WASM module
    const pdfModule = window.wasmModule?.spirepdf;

    // Check that the module is ready
    if (!pdfModule) {
      alert('Spire.PDF is not ready yet');
      return;
    }

    // Load the PDF file to be exported into the VFS
    const inputFileName = 'CustomerInformationForm.pdf';
    await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);

    // Create a PdfDocument object and load the PDF document
    const doc = new pdfModule.PdfDocument();
    doc.LoadFromFile(inputFileName);

    // Build a PdfFormWidget from the document's form handle to reach the data export API
    const formWidget = new pdfModule.PdfFormWidget(doc.Form.H);
    
    // This demo exports XML
    const dataFiles = [
      { fileName: 'FormData.xml', format: pdfModule.DataFormat.Xml },
      // { fileName: 'FormData.fdf', format: pdfModule.DataFormat.Fdf },
      // { fileName: 'FormData.xfdf', format: pdfModule.DataFormat.XFdf },
    ];

    for (const item of dataFiles) {
      // The third parameter is the form name; pass an empty string for an unnamed form
      formWidget.ExportData(item.fileName, item.format, '');
    }
    doc.Close();

    // Read the generated file from the VFS and trigger the download
    for (const item of dataFiles) {
      const fileArray = window.dotnetRuntime.Module.FS.readFile(item.fileName);
      const blob = new Blob([fileArray], { type: 'application/octet-stream' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = item.fileName;
      a.click();
      URL.revokeObjectURL(url);
    }
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Export Form Data</h1>
      <button onClick={exportFormData}>
        Export
      </button>
    </div>
  );
}

export default App;

После завершения вызова экспорта файл данных находится в виртуальной файловой системе. Затем код считывает его из VFS и запускает загрузку в браузере, чтобы файл можно было сохранить, передать или заархивировать вместе с другими данными форм:

Экспортированный файл данных формы XML


Импорт данных формы PDF

Вторая половина цикла — восстановление данных. PdfFormWidget.ImportData считывает файл данных и записывает каждое значение обратно в соответствующее поле формы по имени. Параметр DataFormat указывает парсеру, как интерпретировать содержимое файла; он никак не связан с расширением файла, поэтому объявленный формат должен совпадать с фактическим форматом файла.

Целевым объектом здесь является пустой экземпляр исходной формы. Шаблон отправляется незаполненным; когда файл данных возвращается, все поля заполняются за один проход — без повторного ручного ввода, без копирования поле за полем, без необходимости вводить всё заново:

function App() {
  const importFormData = async () => {
    // Get the Spire.PDF WASM module
    const pdfModule = window.wasmModule?.spirepdf;

    // Check that the module is ready
    if (!pdfModule) {
      alert('Spire.PDF is not ready yet');
      return;
    }

    // Load the blank form to be filled into the VFS
    const inputFileName = 'BlankCustomerInformationForm.pdf';
    await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);

    // This demo refills from the XML data file
    const dataFiles = [
      { fileName: 'FormData.xml', format: pdfModule.DataFormat.Xml, outputFileName: 'ImportedXMLData.pdf' },
      // { fileName: 'FormData.fdf', format: pdfModule.DataFormat.Fdf, outputFileName: 'ImportedFDFData.pdf' },
      // { fileName: 'FormData.xfdf', format: pdfModule.DataFormat.XFdf, outputFileName: 'ImportedXFDFData.pdf' },
    ];

    for (const item of dataFiles) {
      // The data file also has to be loaded into the VFS first
      await window.spire.FetchFileToVFS(item.fileName, "", `${process.env.PUBLIC_URL}/data/`);

      const doc = new pdfModule.PdfDocument();
      doc.LoadFromFile(inputFileName);

      // Read the data file and write the values back into the fields by name
      const formWidget = new pdfModule.PdfFormWidget(doc.Form.H);
      formWidget.ImportData(item.fileName, item.format);

      doc.SaveToFile(item.outputFileName);
      doc.Close();

      // Read the generated file from the VFS and trigger the download
      const fileArray = window.dotnetRuntime.Module.FS.readFile(item.outputFileName);
      const blob = new Blob([fileArray], { type: 'application/pdf' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = item.outputFileName;
      a.click();
      URL.revokeObjectURL(url);
    }
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Import Form Data</h1>
      <button onClick={importFormData}>
        Import
      </button>
    </div>
  );
}

export default App;

После завершения вызова импорта ранее пустая форма полностью заполнена и готова к сохранению или отображению. Результат — новый PDF, в котором каждое поле заполнено данными из файла данных:

Форма после импорта данных XML


Выбор подходящего формата данных

Все три формата содержат идентичные значения полей, поэтому решение сводится к структуре и поддержке инструментами, а не к точности данных. Вот как следует думать о каждом из них в контексте цикла экспорта-импорта данных формы:

  • FDF создаёт файлы наименьшего размера. Он начинается с %FDF- и использует компактную текстовую нотацию, где /T содержит имя поля, а /V — значение. Это делает его эффективным для передачи данных между программами, работающими с формами, однако содержимое нелегко прочитать человеку, и он плохо сочетается с текстовыми инструментами и системами контроля версий.
  • XFDF — это стандартный XML с одним элементом <field> на каждое поле. Поскольку это корректно сформированный XML, его можно сравнивать, объединять и просматривать обычными текстовыми инструментами, что делает его самым безопасным выбором, когда файл данных попадает в систему контроля версий, требует проверки человеком или должен взаимодействовать с другой системой.
  • XML (XML данных формы Adobe) помещает имя поля непосредственно в имя элемента, обеспечивая самую простую структуру из трёх. Он идеален, когда нужно просто получить читаемый список имён полей и значений без лишних формальностей.

Коротко: используйте FDF для циклов, которые остаются внутри одной программы; XFDF — когда файл пересекает границы инструментов или команд; XML — когда читаемость является главным приоритетом.


Часто задаваемые вопросы

Некоторые поля остаются пустыми после импорта

Причина: ImportData сопоставляет данные по имени поля, поэтому имена в файле данных должны в точности совпадать с именами полей в форме — включая регистр и пробелы. Поле, которое не совпало, молча пропускается; ошибки нет и нет возвращаемого значения, указывающего на несовпадение. Значение получают только те поля, чьи имена совпали.

Решение: Перед импортом пройдите по коллекции полей формы и выведите их фактические имена, затем сравните их с файлом данных:

const fields = formWidget.FieldsWidget;
for (let i = 0; i < fields.Count; i++) {
  console.log(fields.get_Item({ index: i }).Name);
}

При импорте возникает ошибка Xml_MessageWithErrorPosition или «not a valid FDF file»

Причина: ImportData разбирает файл в соответствии с форматом, указанным во втором параметре, и никогда не проверяет расширение файла. Когда содержимое не соответствует объявленному формату, разбор немедленно завершается ошибкой: для XML-файлов сообщается Xml_MessageWithErrorPosition, Xml_InvalidRootData, а для файла, не являющегося FDF, — The source is not a valid FDF file because it does not start with "%FDF-".

Решение: Передайте DataFormat, соответствующий фактическому содержимому файла, и используйте исходный экспортированный файл данных, а не тот, который был повторно сохранён в другом формате.


См. также