C# 是否有一种直接的方法可以使用 iTextSharp 将一个 PDF 文档附加到另一个文档?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/566899/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 08:28:22  来源:igfitidea点击:

Is there a straight forward way to append one PDF doc to another using iTextSharp?

c#pdfitextsharp

提问by Danno

I've scoured the Web looking for examples on how to do this. I've found a few that seem to be a little more involved then they need to be. So my question is, using iTextSharp, is there a fairly concise way to append one PDF document to another one?

我已经在网上搜索有关如何执行此操作的示例。我发现一些似乎比他们需要更多的参与。所以我的问题是,使用 iTextSharp,是否有一种相当简洁的方法可以将一个 PDF 文档附加到另一个文档?

Optimally this would NOT involve a third file. Just open the first PDF doc, append the second PDF doc to the first and then close them both.

最佳情况下,这不会涉及第三个文件。只需打开第一个 PDF 文档,将第二个 PDF 文档附加到第一个,然后关闭它们。

采纳答案by Danno

Ok, It's not straight forward, but it works and is surprisingly fast. (And it uses a 3rd file, no such thing as open and append.) I 'discovered' this in the docs/examples. Here's the code:

好的,这不是直截了当的,但它可以工作并且速度非常快。(并且它使用第三个文件,没有打开和附加之类的东西。)我在文档/示例中“发现”了这一点。这是代码:

private void CombineMultiplePDFs( string[] fileNames, string outFile ) {
    int pageOffset = 0;
    ArrayList master = new ArrayList();
    int f = 0;

    Document document = null;
    PdfCopy writer = null;
    while ( f < fileNames.Length ) {
        // we create a reader for a certain document
        PdfReader reader = new PdfReader( fileNames[ f ] );
        reader.ConsolidateNamedDestinations();
        // we retrieve the total number of pages
        int n = reader.NumberOfPages;
        ArrayList bookmarks = SimpleBookmark.GetBookmark( reader );
        if ( bookmarks != null ) {
            if ( pageOffset != 0 ) {
                SimpleBookmark.ShiftPageNumbers( bookmarks, pageOffset, null );
            }
            master.AddRange( bookmarks );
        }
        pageOffset += n;

        if ( f == 0 ) {
            // step 1: creation of a document-object
            document = new Document( reader.GetPageSizeWithRotation( 1 ) );
            // step 2: we create a writer that listens to the document
            writer = new PdfCopy( document, new FileStream( outFile, FileMode.Create ) );
            // step 3: we open the document
            document.Open();
        }
        // step 4: we add content
        for ( int i = 0; i < n; ) {
            ++i;
            if ( writer != null ) {
                PdfImportedPage page = writer.GetImportedPage( reader, i );
                writer.AddPage( page );
            }
        }
        PRAcroForm form = reader.AcroForm;
        if ( form != null && writer != null ) {
            writer.CopyAcroForm( reader );
        }
        f++;
    }
    if ( master.Count > 0 && writer != null ) {
        writer.Outlines = master;
    }
    // step 5: we close the document
    if ( document != null ) {
        document.Close();
    }
}

回答by configurator

Yes. I've seen a class called PdfManipulation posted in an iText forum. Using that class would involve a third file though.

是的。我在 iText 论坛上看到了一个名为 PdfManipulation 的类。但是,使用该类将涉及第三个文件。

The class is originally in VB.Net. I downloaded it from a post on vbforums.com. Apparently though, it doesn't have the merge files function, so I wrote one based on the code in that class.

该类最初在 VB.Net 中。我从vbforums.com 上的一个帖子下载了它。显然,它没有合并文件功能,所以我根据该类中的代码编写了一个。

This was written on a machine without iTextSharp. This might have bugs. I'm not even sure if page numbers are 0-based or 1-based. But give it a shot.

这是在没有 iTextSharp 的机器上编写的。这可能有错误。我什至不确定页码是基于 0 还是基于 1。但试一试。

public static void MergePdfFiles(IEnumerable<string> files, string output) {
    iTextSharp.text.Document doc;
    iTextSharp.text.pdf.PdfCopy pdfCpy;

    doc = new iTextSharp.text.Document();
    pdfCpy = new iTextSharp.text.pdf.PdfCopy(doc, new System.IO.FileStream(output, System.IO.FileMode.Create));
    doc.Open();

    foreach (string file in files) {
        // initialize a reader
        iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(file);
        int pageCount = reader.NumberOfPages;

        // set page size for the documents
        doc.SetPageSize(reader.GetPageSizeWithRotation(1));

        for (int pageNum = 1; pageNum <= pageCount; pageNum++) {
            iTextSharp.text.pdf.PdfImportedPage page = pdfCpy.GetImportedPage(reader, pageNum);
            pdfCpy.AddPage(page);
        }

        reader.Close();
    }

    doc.Close();
}

回答by KeyserSoze

I don't know how to do it for PDF files, but for postscript, you just concatenate the files. If you have pdf2ps and ps2pdf installed, the below will do the job:

我不知道如何处理 PDF 文件,但对于 postscript,您只需连接文件即可。如果您安装了 pdf2ps 和 ps2pdf,以下内容将完成这项工作:

pdf2ps file1.pdf file1.ps
pdf2ps file2.pdf file2.ps
cat file1.ps file2.ps > combined.ps
ps2pdf combined.ps combined.pdf

I'm not an expert on pdf2ps or ps2pdf. I've only ever used ps2pdf, and when I do so, it leaves text as text (I can still select and copy text from the resulting pdf). When I do the above steps (pdf->ps, combine, ps->pdf) I end up with a resulting pdf that is like an image. No idea why.

我不是 pdf2ps 或 ps2pdf 的专家。我只使用过 ps2pdf,当我这样做时,它会将文本保留为文本(我仍然可以从生成的 pdf 中选择和复制文本)。当我执行上述步骤(pdf-> ps,组合,ps-> pdf)时,我最终得到了一个类似于图像的 pdf。不知道为什么。

回答by Loudenvier

I really may be missing something, but I did something much simpler. I concede this solution probably won't update bookmarks (as in the best answer here so far), but it works flawlessly for me. Since I was merging documents with fillable forms, I used PdfCopyFields instead of PdfCopy.

我真的可能遗漏了一些东西,但我做了一些更简单的事情。我承认这个解决方案可能不会更新书签(就像迄今为止最好的答案一样),但它对我来说完美无缺。由于我将文档与可填写表单合并,因此我使用 PdfCopyFields 而不是 PdfCopy。

Here is the code (I've stripped all error handling to make the actual code more visible, add a try..finally to close opened resources if you plan on using the code):

这是代码(我已经剥离了所有错误处理以使实际代码更加可见,如果您打算使用该代码,请添加 try..finally 以关闭打开的资源):

    void MergePdfStreams(List<Stream> Source, Stream Dest)
    {
        PdfCopyFields copy = new PdfCopyFields(Dest);

        foreach (Stream source in Source)
        {
            PdfReader reader = new PdfReader(source);
            copy.AddDocument(reader);
        }

        copy.Close();
    }

You can pass any stream, be it a FileStream, a MemoryStream (useful when reading the PDF from databases, no need for temporary files, etc.)

您可以传递任何流,无论是 FileStream 还是 MemoryStream(从数据库读取 PDF 时很有用,不需要临时文件等)

Sample usage:

示例用法:

    void TestMergePdfStreams()
    {
        List<Stream> sources = new List<Stream>()
        {
            new FileStream("template1.pdf", FileMode.Open),
            new FileStream("template2.pdf", FileMode.Open),
            new MemoryStream((byte[])someDataRow["PDF_COLUMN_NAME"])
        };

        MergePdfStreams(sources, new FileStream("MergedOutput.pdf", FileMode.Create));
    }