【问题标题】:Trying to use PdfStamper and MemoryStream to add data to existing PDF then email it尝试使用 PdfStamper 和 MemoryStream 将数据添加到现有 PDF 然后通过电子邮件发送
【发布时间】:2015-10-13 16:17:04
【问题描述】:

这是我的代码块。它编译得很好,当我触发事件时,我收到了电子邮件,但是我收到了这个错误 打开时在 Adob​​e 上发送电子邮件附件错误(Acrobat 无法打开“Att00002.pdf”,因为它不是受支持的文件类型或文件已损坏(例如,它作为电子邮件附件发送并且未正确解码。)

string agentName = "My Name";            
MemoryStream _output = new MemoryStream();
            PdfReader reader = new PdfReader("/pdf/Agent/Specialist_Certificate.pdf");
            using (PdfStamper stamper = new PdfStamper(reader, _output))
            {
                AcroFields fields = stamper.AcroFields;
            // set form fields
            fields.SetField("FIELD_AGENT_NAME", agentName);
            fields.SetField("FIELD_DATE", AvalonDate);

            // flatten form fields and close document
            stamper.FormFlattening = true;
            SendEmail(_output);
            DownloadAsPDF(_output);
            stamper.Close();
        }

private void SendEmail(MemoryStream ms)
{
    Attachment attach = new Attachment(ms, new System.Net.Mime.ContentType("application/pdf"));
    EmailHelper.SendEMail("myemail@myemail.com", "mjones@globusfamily.com", null, "", "Avalon Cert", "Hope this works", EmailHelper.EmailFormat.Html,attach);
}

已编辑 *******************************************

        using (MemoryStream _output = new MemoryStream())
        {
            using (PdfStamper stamper = new PdfStamper(reader, _output))
            {
                AcroFields fields = stamper.AcroFields;
                // set form fields
                fields.SetField("FIELD_AGENT_NAME", agentName);
                fields.SetField("FIELD_DATE", AvalonDate);

                // flatten form fields and close document
                stamper.FormFlattening = true;
            }
            SendEmail(_output);
        }

【问题讨论】:

  • 在调用SendEmail 之前尝试关闭PdfStamper。您可能只附加了 PDF 字节流的一部分,因为尚未将所有内容刷新到输出。
  • 当我把它改成 stamper.Close();发送电子邮件(_输出);发送电子邮件时收到此错误 System.ObjectDisposedException: Cannot access a closed Stream

标签: c# adobe itextsharp memorystream pdfstamper


【解决方案1】:

您在using (PdfStamper stamper = new PdfStamper(reader, _output)) 中调用stamper.close()。除了手动关闭()之外,using 将在退出时自动关闭压模,因此从技术上讲,压模试图关闭两次。因此,它还试图多次关闭MemoryStream。这就是异常的来源。

我会为您的MemoryStreamPdfStamper 使用此处答案中的技术(修改并取自:Getting PdfStamper to work with MemoryStreams (c#, itextsharp)):

using (MemoryStream _output = new MemoryStream()) {
  using (PdfStamper stamper = new PdfStamper(reader, _output)) {
// do stuff      
  }    
}

【讨论】:

  • 我同意这一点,但我会更进一步,提倡我也经常使用的 kuujinbo 的完整模式,即返回字节数组而不是流。如果您稍后需要一个流,只需用一个新的字节数组包装。是的,那里有几个额外的 CPU 周期,但实际上并不多。传递流的问题正是 UncleRico 所指出的,那就是其他人可以通过关闭它们或设置位置或其他方式来干扰它们。
  • 好的,我会把我的 SendEmail(_output);那么大块呢?如果我把它放在使用 PdfStamper 之外,我会收到一条错误消息,指出流已经关闭。
  • @user1566783 我建议先创建您的加盖 pdf 文件,然后使用上面的代码作为模板关闭它。然后作为辅助过程,使用SendEmail() 方法将其附加到您的电子邮件中。请记住,在一种情况下,您的 MemoryStream 被用于写入信息,而您的附件过程正在使用相同的 MemoryStream 从中读取信息(这并不是一件好事)。
  • 那么你是在说这样的话吗?由于使用正在关闭压模,因此我发送了电子邮件,然后也关闭了内存流的使用。还是像上面克里斯所说的那样,我应该尝试将它放入一个字节数组中,然后以这种方式在附件中发送出去?
  • @user1566783。我喜欢克里斯的方法,但是我已经成功地使用了我的答案中突出显示的内存流。所以两者都行。我自己的偏好是使用两个内存流,一个用于写入新的 pdf,另一个用于读取生成的组合 pdf,以便在您的电子邮件中使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-19
  • 2014-11-15
  • 1970-01-01
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
相关资源
最近更新 更多