假设我在网站上提供了一个pdf表单文件,该文件由用户填写并提交给服务器。在服务器端(Asp.Net),我想将我收到的xml格式的数据与填充的空pdf表单合并并保存。
我发现有几种可能的方法:
由于我没有这种任务的经验,你能建议哪个选项会更好/更容易并提供一些额外的提示吗?
提前谢谢。
答案 0 :(得分:3)
如果可能的话,我建议使用第4种方法,因为它会更清洁。您将使用专门针对您要求的方案量身定制的解决方案,但如果您没有可用于此类解决方案的资源,我建议您使用第一个选项。
第一个选项是我最近潜入的选项。我发现它实施起来相对轻松。
如果以下情况适用,则可以使用选项1:
实施示例:
使用Adobe Acrobat生成PDF表单。提示:生成表单时使用Adobe Native Fonts。对于你添加的不是本机字体的每个控件,它将导入所使用的字体并在未压缩时膨胀文件,据我所知,ITextSharp目前不生成压缩的PDF。
使用ITextSharp Library将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页面的响应中
答案 1 :(得分:0)
由于你标记了这个'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指向的表单。
用户现在应该可以保存表单并填写 - 不需要Reader Extension!
答案 2 :(得分:0)
您还可以使用 iTextSharp 将xml数据填充到启用 Reader Extension 的表单中。您需要正确设置两件事:
PdfReader.unethicalreading = true
以阻止 BadPasswordException。 所以你需要做的就是:
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");
}
}
}