【问题标题】:After filling PDF with iTextSharp, form is not savable/ usage rights removed使用 iTextSharp 填充 PDF 后,表单不可保存/使用权限已删除
【发布时间】:2014-04-13 18:09:39
【问题描述】:

我目前正在研究使用 iTextSharp 部分填写 PDF 表单的流程。然后将该表单通过电子邮件发送给用户,用户将完成表单的填写。然后通过电子邮件将表单提交回我们的电子邮件帐户,然后进行处理。

我的问题是,一旦将 PDF 发送给用户,当用户打开表单并且数据无法保存时。用作模板的原始 PDF 可以填写保存。不知何故,在使用 iTextSharp 的过程中,表单正在失去其使用权。使用 iTextSharp 时有没有办法保留使用权?

我希望这里的人能指出哪里出了问题,或者指出我正确的方向。感谢您的时间和帮助。

下面是代码:

using Dapper;
using iTextSharp.text.pdf;
using NLog;
using PilotDispatch.Domain.Model;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data.OleDb;
using System.IO;
using System.Linq;

namespace eTicketPdfFactory
{
    class Program
    {
        const string TemplateItextPdfPath = @"C:\PDF\Factory\eTicketFormPortrait.pdf";
        const string OutputItextPdfPath = @"C:\PDF\Factory\eTicketFormPortraitOut.pdf";


    private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

        static void Main(string[] args)
        {
            var logid = string.Empty;
            if (args.Length > 0)
            {
                logid = args[0];
            }
            else
            {
                Logger.Error("No LogId supplied");
                return;
            }

            var rundownQuery =
                string.Format(
                    "SELECT * FROM Rundown_Table LEFT JOIN Vessels ON Vessels.CallSign = Rundown_Table.Call_Sign WHERE Rundown_Table.Log_ID = '{0}'",
                    logid);


            ETicketPdf ticket;
            IEnumerable<PilotTransportation> pilotTransportations = null;

            using (var cn = new OleDbConnection(ConfigurationManager.ConnectionStrings["PervasiveConnection"].ConnectionString))
            {
                cn.Open();
               // ticket = cn.Query<ETicketPdf>(PervasiveQueryString, new { Log_ID = logid }).FirstOrDefault(); // not working with Pervasive
                ticket = cn.Query<ETicketPdf>(rundownQuery).FirstOrDefault();

                if (ticket != null)
                {
                    var transportationQuery =
                        string.Format(
                            "SELECT * FROM PilotTransportation WHERE PilotCode = '{0}'",
                            ticket.Pilot_Code);

                    pilotTransportations = cn.Query<PilotTransportation>(transportationQuery);
                }

                cn.Close();
            }

            if (ticket == null)
            {
                Logger.Error("No records found for given LogId");
                return;
            }

           var pilotOptions = pilotTransportations.Select(opt => string.Format("{0} - {1}", opt.VendorID, opt.Name)).ToArray();


            var reader = new PdfReader(TemplateItextPdfPath);
            var stamper = new PdfStamper(reader, new FileStream(OutputItextPdfPath, FileMode.Open));
            //var stamper = new PdfStamper(reader, new FileStream(OutputItextPdfPath, FileMode.CreateNew, FileAccess.Write), '\0', true);
            var formFields = stamper.AcroFields;

            formFields.SetListOption("Form[0].Page1[0].VendorIdFrom1[0]", null, pilotOptions);
            formFields.SetListOption("Form[0].Page1[0].VendorIdTo1[0]", null, pilotOptions);
            formFields.SetListOption("Form[0].Page1[0].VendorIdFrom2[0]", null, pilotOptions);
            formFields.SetListOption("Form[0].Page1[0].VendorIdTo2[0]", null, pilotOptions);

            var properties = ticket.GetType().GetProperties();

            foreach (var prop in properties)
            {
                var name = prop.Name;
                var propval = prop.GetValue(ticket, null);

                if (propval != null)
                {
                    if (name == "Order_Date")
                    {
                        if(Convert.ToDateTime(propval).Year < 1902)continue;
                    }

                    formFields.SetField(name, propval.ToString());
                }

            }

            reader.RemoveUsageRights();
            stamper.Close();
            reader.Close();

            File.Copy(OutputItextPdfPath, Path.GetDirectoryName(OutputItextPdfPath) + "/" + logid + ".pdf");

            Console.WriteLine("finished");
            Console.ReadLine();
        }
    }
}

再次感谢您提供的任何指点或帮助。

【问题讨论】:

    标签: c# pdf pdf-generation adobe itextsharp


    【解决方案1】:

    答案在你自己的源代码中注释掉。

    你需要:

    var stamper = new PdfStamper(reader, new FileStream(...), '\0', true);
    

    代替:

    var stamper = new PdfStamper(reader, new FileStream(...));
    

    您的问题与How to correctly fill in XFA form data using iTextSharp to allow editing and saving result in Acrobat XI 重复 你可以找到更详细的答案here

    另外:您抱怨使用权限被删除,但如果是这样,为什么我会在您的代码中看到这一行:

    reader.RemoveUsageRights();
    

    该行删除了使用权限,因此在使用 Adob​​e Reader 时无法再在本地保存表单。

    【讨论】:

    • 一个是问题的链接,另一个是答案的链接。除了你的代码,没有什么可以修复的。如果我能给你更多建议:请在以后阅读文档。如果您使用名为RemoveUsageRights() 的方法,询问为什么删除使用权会很尴尬。
    • 抱歉,我在代码中留下了使用权限调用。那是出于测试目的。另外,我已经交换了您上面所说的代码行。然而结果仍然不可行。如果我通过电子邮件给自己发送原始 PDF,我可以填写并提交并从提交的 pdf 中获取数据。但是,如果我使用新创建的 PDF,我会收到来自 PDF Expert 的警告,指出“由于文件结构的原因,无法保存表单数据。请在最新版本的 Adob​​e Live Cycle Designer 中重新保存文件。”因此,随着您的更改,正在使用 iTextSharp 更改某些内容。 @布鲁诺
    • 另外...从生成的 PDF 提交数据后,我可以看到用户在 Outlook 2013 的 PDF 预览中填写的数据,但看不到预填充的数据.如果我在阅读器或 acrobat 中打开 PDF,情况正好相反。我可以看到预填充的数据,但看不到用户提交的数据。因此,数据确实在某些级别上出现在表格上,但不是在女士级别上。 @Bruno Lowagie
    • 您使用的是旧版本的 iText 吗?这听起来像是一个不久前解决的问题。
    • 你是对的。我使用的是 iTextSharp 版本 4.5... 将其替换为 5.5... 但是现在四个下拉列表没有像以前那样被填充。 formFields.SetListOption("Form[0].Page1[0].VendorIdFrom1[0]", null, PilotOptions) 不再起作用。可能的更新问题?
    猜你喜欢
    • 1970-01-01
    • 2015-04-17
    • 2013-01-08
    • 1970-01-01
    • 2013-02-20
    • 1970-01-01
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多