
Когда форма 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 и запускает загрузку в браузере, чтобы файл можно было сохранить, передать или заархивировать вместе с другими данными форм:

Импорт данных формы 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, в котором каждое поле заполнено данными из файла данных:

Выбор подходящего формата данных
Все три формата содержат идентичные значения полей, поэтому решение сводится к структуре и поддержке инструментами, а не к точности данных. Вот как следует думать о каждом из них в контексте цикла экспорта-импорта данных формы:
-
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, соответствующий фактическому содержимому файла, и используйте исходный экспортированный файл данных, а не тот, который был повторно сохранён в другом формате.