使用xml数据合并/填充pdf表单文件

假设我在网站上有一个pdf表单文件,由用户填写并提交给服务器 . 在服务器端(Asp.Net),我想将我以xml格式接收的数据与填充的空pdf表单合并并保存 .

我发现有几种可能的方法:

  • 使用adobe acrobat创建的pdf表单并用itextsharp填充 .

  • 使用adobe acrobat创建的pdf表单并填充FDF Toolkit .net(似乎在内部使用itextsharp)

  • usd pdfkt填写表格 .

  • 使用使用adobe livecycle创建的pdf表单文件,并使用Form Data Integration Service合并数据

由于我没有这种任务的经验,你能建议哪个选项会更好/更容易并提供一些额外的提示吗?

先感谢您 .

回答(3)

2 years ago

如果可能的话,我建议使用第4种方法,因为它会更清洁 . 您将使用专门为您要求做的定制的解决方案,但如果您没有可用于此类解决方案的资源,我建议您使用第一个选项 .

第一个选项是我最近潜入的选项 . 我发现它实施起来相对轻松 .

如果以下情况适用,则可以选择1:

  • 您可以控制PDF表单的开发 .

  • 您可以控制格式化xml数据

  • 您可以使用未压缩(fastweb = false)PDF文件

实施示例:

  • 使用Adobe Acrobat生成PDF表单 . 提示:生成表单时使用Adobe Native Fonts . 对于您添加的不是本机字体的每个控件,它将导入所使用的字体并在未压缩文件时使文件膨胀,据我所知,ITextSharp当前不生成压缩的PDF .

  • 使用ITextSharp库将XML数据与PDF表单组合以生成填充的文档 . 提示:要从xml手动填充PDF表单,您必须将xml值映射到PDF表单中的控件名称,并按页面进行匹配,如下例所示 .

using (MemoryStream stream = GeneratePDF(m_FormsPath, oXmlData))
{
      byte[] bytes = stream.ToArray();
      Response.ContentType = "application/pdf";
      Response.BinaryWrite(bytes);
      Response.End();
}

// <summary>
// This method combines pdf forms with xml data
// </summary>
// <param name="m_FormName">pdf form file path</param>
// <param name="oData">xml dataset</param>
// <returns>memory stream containing the pdf data</returns>
private MemoryStream GeneratePDF(string m_FormName, XmlDocument oData)
{
PdfReader pdfTemplate;
PdfStamper stamper;
PdfReader tempPDF;
Document doc;
MemoryStream msTemp;
PdfWriter pCopy;
MemoryStream msOutput = new MemoryStream();

pdfTemplate = new PdfReader(m_FormName);

doc = new Document();
pCopy = new PdfCopy(doc, msOutput);

pCopy.AddViewerPreference(PdfName.PICKTRAYBYPDFSIZE, new PdfBoolean(true));
pCopy.AddViewerPreference(PdfName.PRINTSCALING, PdfName.NONE);

doc.Open();

for (int i = 1; i < pdfTemplate.NumberOfPages + 1; i++)
{
    msTemp = new MemoryStream();
    pdfTemplate = new PdfReader(m_FormName);

    stamper = new PdfStamper(pdfTemplate, msTemp);

    // map xml values to pdf form controls (element name = control name)
    foreach (XmlElement oElem in oData.SelectNodes("/form/page" + i + "/*"))
    {
        stamper.AcroFields.SetField(oElem.Name, oElem.InnerText);
    }

    stamper.FormFlattening = true;
    stamper.Close();
    tempPDF = new PdfReader(msTemp.ToArray());
    ((PdfCopy)pCopy).AddPage(pCopy.GetImportedPage(tempPDF, i));
    pCopy.FreeReader(tempPDF);
}

doc.Close();

return msOutput;
}
  • 保存文件或将文件发布到ASP.Net页面的响应中

2 years ago

既然你标记了这个'LiveCycle',我认为你在某个地方安装了Adobe LiveCycle(可选,可以在某处安装) .

在这种情况下,我会选择4号(使用Adobe LiveCycle Forms ES模块进行修改) . 从长远来看,其他三个无疑会产生兼容性问题 . 使用LiveCycle服务器(运行Forms模块),您将能够处理任何PDF,无论是旧的,新的,静态的,动态的,压缩的,基于Acrobat的还是基于LiveCycle的 .

您应该能够进行设置,让表单将其数据发送到LiveCycle服务器,并使用该数据填充表单 . 然后,填充可以存储在服务器的数据库中,或者路由到PDF表单(或任何其他表单)并流式传输回客户端 .

使用LiveCycle Designer创建表单 .

快速和脏选项如下:将表单设置为http-post(例如xfdf,请参阅Acrobat以获取更多信息)到ASP服务器并将其发布到服务器上(确保您的用户不要在打开表单之前下载表单,否则这将无效 . 表单必须在Web浏览器中打开) . 然后,只需捕获提交内容,就像从网页捕获http-post一样 . (可选)将填充保存到数据库 . 然后将捕获的xfdf流填充发送回客户端(也可以在稍后阶段通过http-link调用) . xfdf流将包含用于填充它的表单的URL . 客户端Web浏览器将要求Acrobat / Adobe reader插件处理xfdf流,插件将找到,下载并填充xfdf指向的表单 .

用户现在应该能够保存表单并填写 - 无需读者扩展!

2 years ago

您还可以使用iTextSharp将xml数据填充到启用了Reader Extension的表单中 . 您需要正确设置两件事:

  • 设置 PdfReader.unethicalreading = true 以防止 BadPasswordException.

  • 在PdfStamper的构造函数中设置 append mode ,否则Adobe Reader Extensions签名将被破坏,Adobe Reader将显示以下消息:"This document contained certain rights to enable special features in Adobe Reader. The document has been changed since it was created and these rights are no longer valid. Please contact the author for the original version of this document."

所以你需要做的就是:

PdfReader.unethicalreading = true;
using (var pdfReader = new PdfReader("form.pdf"))
{
    using (var outputStream = new FileStream("filled.pdf", FileMode.Create, FileAccess.Write))
    {
        using (var stamper = new iTextSharp.text.pdf.PdfStamper(pdfReader, outputStream, '\0', true))
        {
            stamper.AcroFields.Xfa.FillXfaForm("data.xml");
        }
    }
}

How to fill XFA form using iText?