【问题标题】:How to load a PDF from a stream and add a file attachment?如何从流中加载 PDF 并添加文件附件?
【发布时间】:2015-03-28 10:09:52
【问题描述】:

我正在使用 MS SQL Report Server Web 服务生成 PDF 格式的报告:

byte[] Input;
ReportServer report = new ReportServer(serverUrl + @"/ReportExecution2005.asmx", reportPath);
Input = report.RenderToPDF(reportParamNames, reportParamValues);

此服务返回一个带有 pdf 文件的字节数组。

我需要将此字节数组加载到 iTextSharp:

using (MemoryStream ms = new MemoryStream(Input)) {
    Document doc = new Document();
    PdfWriter writer = PdfWriter.GetInstance(doc, ms);
    doc.Open();
    ...
}

这似乎没问题,但我正在尝试在此 PDF 中添加附件:

PdfFileSpecification pfs = PdfFileSpecification.FileEmbedded(writer, xmlInputFile, xmlFileDisplayName, null);
writer.AddFileAttachment(pfs);

这看起来也不错,但是当我将流保存到文件时,生成的 pdf 不正确。

请注意,文件附件将始终是一个 XML 文件,我需要在内存中创建它,并且永远不会在文件系统中。如何使用 iTextSharp 做到这一点?

【问题讨论】:

  • 我什至不知道从哪里开始,你的代码都是错误的,你需要使用 PdfStamper,创建一个新的 PDF 并阅读文档。
  • 我是 iTextSharp 库的新手,抱歉 :-)

标签: c# pdf reporting-services itextsharp


【解决方案1】:

我读到了:

此服务返回一个带有 pdf 文件的字节数组。 我需要将此字节数组加载到 iTextSharp:

using (MemoryStream ms = new MemoryStream(Input))
{
  Document doc = new Document();
  PdfWriter writer = PdfWriter.GetInstance(doc, ms);
  doc.Open();
  ...
}

这看起来不错

这是好的。您想向现有 PDF 文件添加附件,但是,您正在使用 DocumentPdfWriter 这两个类来从头开始创建新的 PDF 文档

请阅读documentation。有一个方便的表格 (6.1) 可以让您概述不同的类以及何时使用它们。

我引用PdfReaderPdfStamper类的描述:

PdfReader:读取 PDF 文件。您将此类的一个实例传递给一个 其他 PDF 操作类。

PdfStamper: 处理一个(并且只有一个)PDF 文档。可以使用 在绝对位置添加内容、添加额外页面或填充 出领域。保留所有交互功能,除非您 显式删除它们(例如,通过展平表单)。

我们已经确定您做错了:您应该使用PdfReaderPdfStamper 而不是DocumentPdfWriter。现在我们来看看some examples

PdfReader reader = new PdfReader(pdf_bytes);
using (var ms = new MemoryStream()) {
    using (PdfStamper stamper = new PdfStamper(reader, ms)) {
        PdfFileSpecification pfs = PdfFileSpecification.FileEmbedded(
            stamper.Writer, xmlInputFile, xmlFileDisplayName, null);
        stamper.AddFileAttachment(pfs);
    }
    reader.Close();
    return ms.ToArray();
}

如您所见,我们使用保存在内存中的字节创建了一个PdfReader 实例。然后我们使用PdfStamper 创建一个新的MemoryStream,我们使用其中的字节。

更多答案请关注The Best iText Questions on StackOverflow

【讨论】:

    【解决方案2】:

    不想创建重复项,将其发布在这里.. 代码似乎不起作用,尽管文件附件最终已损坏,但它确实将某些内容附加到 pdf 中。亲自尝试,在我的例子中是一个 URL:

        static void Main(string[] args)
        {
            byte[] file_bytes = File.ReadAllBytes(@"./legit.pdf");
            byte[] modified_bytes = GeneratePDFByte(file_bytes);
            File.WriteAllBytes(@"./modified.pdf", modified_bytes);
        }
    
        private static byte[] GeneratePDFByte(byte[] pdf_bytes)
        {
            PdfReader reader = new PdfReader(pdf_bytes);
            using (var ms = new MemoryStream())
            {
                using (PdfStamper stamper = new PdfStamper(reader, ms))
                {
                    PdfFileSpecification pfs = PdfFileSpecification.Url(stamper.Writer, "https://itextpdf.com/sites/default/files/styles/max_1300x1300/public/2019-08/Octocat.png");
                    stamper.AddFileAttachment("file", pfs);
                }
                reader.Close();
                return ms.ToArray();
            }
        }
    

    这与我以前的帖子有关(因此您可以了解全貌): How to insert an external ressource within a PDF dcument?

    【讨论】:

      猜你喜欢
      • 2011-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-30
      • 1970-01-01
      • 2019-06-07
      相关资源
      最近更新 更多