PDF 填写不正确合并

PDF fill in not merging correctly

我们正在使用 asp.net 网站,版本为 iTextSharp.dll 5.5.13 我们可以使用流将多个 PDF 文件合并为一个文件,并且效果很好。但是,当我们使用在 "fill-in" 函数中创建的 PDF 时,新的 PDF 文件不会正确地合并到其他文档中。它在没有填充值的情况下合并。但是,如果我打开填充的 PDF,它会创建填充的数据显示和打印。

我稍后尝试合并新的 "filled in" PDF,但它仍然显示模板文件,就好像填写的数据丢失了一样。

下面代码填写数据

Dim strFileName As String = Path.GetFileNameWithoutExtension(strSourceFile)
Dim strOutPath As String = HttpContext.Current.Server.MapPath("~/Apps/Lifetime/OfficeDocs/Export/")
newFile = strOutPath & strFileName & " " & strRONumber & ".pdf"

If Not File.Exists(newFile) Then
    Dim pdfReader As PdfReader = New PdfReader(strSourceFile)
    Using pdfStamper As PdfStamper = New PdfStamper(pdfReader, New FileStream(newFile, FileMode.Create))

        Dim pdfFormFields As AcroFields = pdfStamper.AcroFields
        pdfFormFields.SetField("CUSTOMER NAME", strCustomer)
        pdfFormFields.SetField("YR MK MODEL", strVehicle)
        pdfFormFields.SetField("RO#", strRONumber)

        pdfStamper.FormFlattening = False
        pdfStamper.Dispose()
    End Using

End If

然后下面的代码合并发送给它的多个 PDF files/paths

Public Shared Sub MergePDFs(ByVal files As List(Of String), ByVal filename As String)
    'Gets a list of full path files and merges into one memory stream
    'and outputs it to a browser response.
    Dim MemStream As New System.IO.MemoryStream
    Dim doc As New iTextSharp.text.Document
    Dim reader As iTextSharp.text.pdf.PdfReader
    Dim numberOfPages As Integer
    Dim currentPageNumber As Integer
    Dim writer As iTextSharp.text.pdf.PdfWriter = iTextSharp.text.pdf.PdfWriter.GetInstance(doc, MemStream)
    doc.Open()
    Dim cb As iTextSharp.text.pdf.PdfContentByte = writer.DirectContent
    Dim page As iTextSharp.text.pdf.PdfImportedPage
    Dim strError As String = ""

    For Each strfile As String In files
        reader = New iTextSharp.text.pdf.PdfReader(strfile)
        numberOfPages = reader.NumberOfPages
        currentPageNumber = 0
        Do While (currentPageNumber < numberOfPages)
            currentPageNumber += 1
            doc.SetPageSize(reader.GetPageSizeWithRotation(currentPageNumber))
            doc.NewPage()
            page = writer.GetImportedPage(reader, currentPageNumber)
            cb.AddTemplate(page, 0, 0)
        Loop
    Next
    doc.Close()
    doc.Dispose()

    If MemStream Is Nothing Then
        HttpContext.Current.Response.Write("No Data is available for output")
    Else
        HttpContext.Current.Response.Clear()
        HttpContext.Current.Response.ContentType = "application/pdf"
        HttpContext.Current.Response.AppendHeader("Content-Disposition", "inline; filename=" + filename)
        HttpContext.Current.Response.BinaryWrite(MemStream.ToArray)
        HttpContext.Current.Response.OutputStream.Flush()
        HttpContext.Current.Response.OutputStream.Close()
        HttpContext.Current.Response.OutputStream.Dispose()
        MemStream.Close()
        MemStream.Dispose()
    End If
End Sub

我希望文件列表中的 "filled in" PDF 保留填写的数据,但它没有。即使我稍后尝试合并填充的文件,它仍然会丢失填充的数据。如果我打印填写的文件,它看起来很完美。

PdfWriter.GetImportedPage只returns你复制了页面内容。这 包括任何注释,特别是不包括当前页面上表单字段的小部件注释。

要同时复制源页面的注释,请改用 iText PdfCopy class。此 class 旨在复制包含所有注释的页面。此外,它还包括一步复制源文档所有页面的方法。

您必须告诉 PdfCopy 对象合并字段,否则将不会构建 文档范围内的 表单结构。

顺便说一句,您的代码创建了许多 PdfReader 对象但没有关闭它们。这可能会大大增加您的内存需求。

因此:

Public Shared Sub MergePDFsImproved(ByVal files As List(Of String), ByVal filename As String)
    Using mem As New MemoryStream()
        Dim readers As New List(Of PdfReader)
        Using doc As New Document
            Dim copy As New PdfCopy(doc, mem)
            copy.SetMergeFields()
            doc.Open()
            For Each strfile As String In files
                Dim reader As New PdfReader(strfile)
                copy.AddDocument(reader)
                readers.Add(reader)
            Next
        End Using
        For Each reader As PdfReader In readers
            reader.Close()
        Next

        HttpContext.Current.Response.Clear()
        HttpContext.Current.Response.ContentType = "application/pdf"
        HttpContext.Current.Response.AppendHeader("Content-Disposition", "inline; filename=" + filename)
        HttpContext.Current.Response.BinaryWrite(mem.ToArray)
        HttpContext.Current.Response.OutputStream.Flush()
        HttpContext.Current.Response.OutputStream.Close()
        HttpContext.Current.Response.OutputStream.Dispose()
    End Using
End Sub

实际上我不确定 CloseDispose 响应输出流是否是个好主意,这不应该是 PDF 的责任合并方法。

是 iText Java 版本的相关答案;您可能需要阅读它以获取更多信息。不幸的是,该答案中的许多链接同时已失效。