Why Telerik PDF Page Extraction Strips Form Fields (and How to Fix It)
The Problem: PDF Form Fields Disappear After Telerik Page Extraction
When extracting pages from a multi-page PDF in .NET using Telerik Document Processing (specifically PdfStreamWriter), developers often run into a baffling issue: the resulting page looks visually perfect, but downstream tools (such as CutePDF SDK, iText, or Adobe Acrobat) can no longer detect or fill out any interactive form fields (AcroForms).
You might run code similar to this:
var output = new MemoryStream();
using (var fileSource = new PdfFileSource(pdfStream))
{
var firstPage = fileSource.Pages.FirstOrDefault();
using (var writer = new PdfStreamWriter(output, leaveStreamOpen: true))
{
using (var resultPage = writer.BeginPage(firstPage.Size))
{
resultPage.WriteContent(firstPage);
}
}
}
After passing this output to another SDK or calling setField(key, value), nothing happens—no exceptions are thrown, yet no form data gets populated. Here is why this happens and how you can resolve it.
The Root Cause: Visual Streams vs. Interactive AcroForms
In the PDF specification, page content and interactive form fields live in entirely different places:
- Content Streams: Handled by
WriteContent(), this layer consists of operators that render vector graphics, text shapes, and images. It represents the visual representation of the page. - Interactive Elements (AcroForm & Annotations): Fillable fields are represented by Widget Annotations linked to a document-level
/AcroFormcatalog dictionary.
Telerik's low-level PdfStreamWriter is designed to copy only the raw visual content streams. When you invoke resultPage.WriteContent(firstPage), it copies the visual appearance but discards page annotations, widget dictionaries, and the global document form registry. To the naked eye, the document looks like a form, but under the hood, it is effectively flattened into a static picture.
Solution 1: Use RadFixedDocument with PdfFormatProvider
To retain interactive form elements, you must use Telerik's higher-level DOM library, RadPdfProcessing, which parses and retains form fields and annotations across pages.
Instead of copying low-level page streams, import the entire document, remove the unwanted trailing pages, and export the document again. This preserves the document catalog and AcroForm structure intact:
using System.IO;
using Telerik.Windows.Documents.Fixed.FormatProviders.Pdf;
using Telerik.Windows.Documents.Fixed.Model;
public static byte[] ExtractFirstPagePreservingForms(Stream sourcePdfStream)
{
var provider = new PdfFormatProvider();
RadFixedDocument document = provider.Import(sourcePdfStream);
// Remove all pages except the first one
while (document.Pages.Count > 1)
{
document.Pages.RemoveAt(document.Pages.Count - 1);
}
using (var outputStream = new MemoryStream())
{
provider.Export(document, outputStream);
return outputStream.ToArray();
}
}
Because you are modifying the existing document rather than creating a blank one from raw stream operations, the root /AcroForm dictionary and field definitions remain associated with the first page.
Solution 2: Keep Stream Positions in Mind
A common secondary bug when working with MemoryStream occurs when converting streams to byte arrays. If you write to a MemoryStream and immediately pass it downstream without resetting the pointer, readers might see an empty stream:
output.Position = 0; // Ensure stream reader starts at the beginning
byte[] bArray = output.ToArray();
Summary
PdfStreamWriter.WriteContent() only clones the visual layout, not the interactive metadata. When splitting multi-page interactive forms, always work with the complete document model (such as RadFixedDocument) and prune unwanted pages rather than extracting raw page streams into a new document.