是否有任何方法可以使用 ABCpdf 抑制“是否要在关闭前保存对 xxx.pdf 的更改”对话框

Posted

技术标签:

【中文标题】是否有任何方法可以使用 ABCpdf 抑制“是否要在关闭前保存对 xxx.pdf 的更改”对话框【英文标题】:Is there any way of suppressing ‘Do you want to save changes to xxx.pdf before closing’ dialog using ABCpdf 【发布时间】:2014-12-10 16:47:02 【问题描述】:

我们正在使用 ABCpdf 读取 adobe 表单模板,使用从数据库中检索到的值填充表单字段并将它们修改为单个 PDF 文档,并将文档作为 HTTP 响应中的文件流发送回 ASP.net MVC 中的用户应用程序。

这种方法运行良好,并且可以成功生成 PDF 文档。但是,当用户选择打开生成的 PDF 文件并尝试关闭它时,Adobe Acrobat 会提示他们“是否要在关闭前保存对 xxx.pdf 的更改”对话框。有什么方法可以使用 ABC pdf 来抑制这条消息?

以下是我们用来生成 PDF 的代码。

public byte[] GeneratePDF(Employee employee, String TemplatePath)
    
        string[] FieldNames;
        Doc theDoc;
        MemoryStream MSgeneratedPDFFile = new MemoryStream();

        //Get the PDF Template and read all the form fields inside the template
        theDoc = new Doc();
        theDoc.Read(HttpContext.Current.Server.MapPath(TemplatePath));
        FieldNames = theDoc.Form.GetFieldNames();

        //Navigate through each Form field and populate employee details 
        foreach (string FieldName in FieldNames)
        
            Field theField = theDoc.Form[FieldName];
            switch (FieldName)
            
                case "Your_First_Name":
                    theField.Value = employee.FirstName;
                    break;
                default:
                    theField.Value = theField.Name;
                    break;
            
            //Remove Form Fields and replace them with text
            theField.Focus();
            theDoc.Color.String = "240 240 255";
            theDoc.FillRect();
            theDoc.Rect.Height = 12;
            theDoc.Color.String = "220 0 0";
            theDoc.AddText(theField.Value);
            theDoc.Delete(theField.ID);
        

        return theDoc.GetData();
    

【问题讨论】:

也在寻找这个问题的答案... 这是最近(2016 年)Adobe Reader 更新中出现的一个非常烦人的“功能”。 Adobe 声称 Reader 会在打开时检查并“修复”损坏的文件,因此——即使 Reader 不允许编辑文档——它也会“修复”它,然后提示您保存修复后的版本。虽然并非所有文档都这样做,但很多文档都会这样做,如果您是 PDF 的用户,那么节省或不保存文档会浪费您的大量时间。 允许阅读器修改和保存文档增加了一个“问题”,可以在 PDF 中包含“元数据”,最简单的是作者、创建者和标题。如果文档具有标题元数据,它将在使用 Chrome 阅读文档时显示,即从网站打开,但是阅读器“修改”元数据并且不再显示在 Chrome 中,这在我的文档中不是特别有用的“改进”意见? 【参考方案1】:

今天我也遇到了这个问题,但是 PDF 没有表单域。我运行了@CharlieNoTomatoes 代码并确认 FieldNames 集合肯定是空的。

我逐步检查了代码的各个阶段,发现如果我将 PDF 保存到文件系统并从那里打开它就可以了。这将其缩小到获取 abcpdf 数据流并将其直接发送给用户的代码(我通常不费心实际保存到磁盘)。在WebSuperGoo docs 中找到了这个,它表明我的服务器可能在响应中发送了一些额外的垃圾,导致文件损坏。

添加Response.End(); 对我有用。生成的 PDF 文件不再显示该消息。

byte[] theData = _thisPdf.Doc.GetData();
var curr = HttpContext.Current;
curr.Response.Clear();
curr.Response.ContentType = "application/pdf";
curr.Response.AddHeader("Content-Disposition", "attachment; filename=blah.pdf");
curr.Response.Charset = "UTF-8";
curr.Response.AddHeader("content-length", theData.Length.ToString());
curr.Response.BinaryWrite(theData);
curr.Response.End();

【讨论】:

【参考方案2】:

我也遇到了这个问题。我找到了关于“外观流”here的提示:

    PDF 包含表单域,并且交互式表单字典中的 NeedAppearances 条目设置为 true。这意味着符合要求的 PDF 阅读器将在 PDF 中的表单字段需要时生成外观流,因此启用了“保存”按钮。如果 NeedAppearances 条目设置为 false,则符合要求的 PDF 阅读器不应生成任何新的外观流。有关 PDF 文件中的外观流以及如何使用 Debenu Quick PDF Library 控制它们的更多信息。

所以,我在 websupergoo doc 中寻找“外观”的东西,并且能够设置一些表单属性并调用字段方法来摆脱“保存更改”消息。在上面的代码示例中,它看起来像这样:

编辑:在使用 AddImagehtml 创建 PDF 并通过设置表单 NeedAppearances 标志无法修复后,使用快速且有用的 WebSuperGoo 支持就同一消息交换电子邮件后,我添加了以下行关于 Catalog 和 Atom 以删除在 AddImageHtml 期间设置的核心文档 NeedAppearances 标志。

public byte[] GeneratePDF(Employee employee, String TemplatePath)

    string[] FieldNames;
    Doc theDoc;
    MemoryStream MSgeneratedPDFFile = new MemoryStream();

    //Get the PDF Template and read all the form fields inside the template
    theDoc = new Doc();
    theDoc.Read(HttpContext.Current.Server.MapPath(TemplatePath));
    FieldNames = theDoc.Form.GetFieldNames();

    //Tell PDF viewer to not create its own appearances
    theDoc.Form.NeedAppearances = false;
    //Generate appearances when needed
    theDoc.Form.GenerateAppearances = true;

    //Navigate through each Form field and populate employee details 
    foreach (string FieldName in FieldNames)
    
        Field theField = theDoc.Form[FieldName];
        switch (FieldName)
        
            case "Your_First_Name":
                theField.Value = employee.FirstName;
                break;
            default:
                theField.Value = theField.Name;
                break;
        

        //Update the appearance for the field
        theField.UpdateAppearance();

        //Remove Form Fields and replace them with text
        theField.Focus();
        theDoc.Color.String = "240 240 255";
        theDoc.FillRect();
        theDoc.Rect.Height = 12;
        theDoc.Color.String = "220 0 0";
        theDoc.AddText(theField.Value);
        theDoc.Delete(theField.ID);
    

    Catalog cat = theDoc.ObjectSoup.Catalog;
    Atom.RemoveItem(cat.Resolve(Atom.GetItem(cat.Atom, "AcroForm")), "NeedAppearances");

    return theDoc.GetData();

【讨论】:

以上是关于是否有任何方法可以使用 ABCpdf 抑制“是否要在关闭前保存对 xxx.pdf 的更改”对话框的主要内容,如果未能解决你的问题,请参考以下文章

选择性地抑制未使用 lambda 的“未使用变量”警告

有没有办法抑制 Xcode 中的警告?

WebSupergoo.ABCpdf8.Doc.Read() 函数未加载字段

以不安全的格式保存数字签名邮件时,如何抑制是/否提示?

抑制xcodebuild输出或减少冗长[重复]

我可以在 SSIS 中抑制“对于每个文件的枚举器为空”警告吗?