【问题标题】:Can I detect the current page when parsing a PDF from user-input HTML via iTextsharp?通过 iTextsharp 从用户输入的 HTML 解析 PDF 时,我可以检测到当前页面吗?
【发布时间】:2013-11-26 17:33:48
【问题描述】:

我正在根据用户输入的 HTML 生成一个非常大的 PDF(300 多页)。多亏了一些很棒的样本,我才能很好地工作。我的下一个要求是生成一个动态目录,其中包含指向 PDF 中章节开始位置的内部链接。我有一部分工作。我可以创建有效的内部 PDF 链接。我需要帮助的部分是页码未知。我尝试先创建主 PDF,然后根据查找文本“第一章”来获取页码,但考虑到文档的大小和章节的数量,它太慢了。

我可以在添加到文档时检测当前页码吗?当我从 HTML 创建 PDF 时,我知道何时进入新章节,但是有没有办法询问 iTextSharp 我们当前在哪个页面上,以便我可以在目录中使用该数字?这样我就可以将它与主文档一起构建,然后将它们合并?有更好的想法吗?

这就是我从用户输入的 HTML 生成 PDF 的方式:

Dim document As New Document()

Dim strManualFile As String = "file.pdf"

PdfWriter.GetInstance(document, New FileStream(strManualFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
document.Open()

Dim htmlarraylistBody As List(Of IElement) = iTextSharp.text.html.simpleparser.HTMLWorker.ParseToList(New StringReader(GetManualHTML()), Nothing)
For l As Integer = 0 To htmlarraylistBody.Count - 1

   document.Add(DirectCast(htmlarraylistBody(l), IElement))

Next

document.Close()
document.Dispose()

【问题讨论】:

    标签: vb.net itextsharp


    【解决方案1】:

    PdfWriter.GetInstance() 返回一个对象,您可以查询该对象以查找当前页码,所以这是您应该知道的第一件事。如果你可以控制你的 HTML,我会注入一个标志变量,你可以稍后在 For 循环中观察它。如果找到标志变量,就做点什么,否则就照常添加内容。

    只是一个快速警告,HTMLWorker 已被弃用很长时间,并且没有得到维护。所有工作都在支持 CSS 的 XmlWorker 库中完成。如果您因为许可证更改而无法使用旧版本you should probably read this,请找出有关旧许可证的神话和事实。

    以下是展示标志变量的完整工作示例。在顶部,我创建了一些示例 HTML,您显然可以将其删除并替换为您的真实 HTML。然后我创建一个标准文档并像您一样遍历每个项目。在循环内部,我检查标志变量,如果找到则存储它,否则就像你做的那样添加元素。

    此代码针对 iTextSharp 5.4.4。如果您使用的是旧版本的 iTextSharp,那么 Using 语句可能不起作用,只需将它们转换为 Dim 语句并删除 End Using (或升级到最新版本)。其他 cmets 见代码

    ''//File to write to
    Dim TestFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Test.pdf")
    
    ''//Create a flag value to search for. We won't write this to the PDF, it is just for searching.
    Dim FlagValue = "!!UNIQUE TEXT!!"
    
    ''//Build our sample HTML. The real version of this would get the HTML from another source ideally.
    Dim sampleHTML = <body/>
    For I As Integer = 1 To 10
    
        ''//Just before inserting our chapter headings we insert our flag value appended with the current chapter number.
        ''//NOTE: This might need to be played with a little bit. I'm not sure if a new page is created by the previous entity
        ''//      closing or the new entity starting.
        sampleHTML.Add(String.Format("{0}{1}", FlagValue, I))
        sampleHTML.Add(<h1><%= String.Format("Chapter {0}", I) %></h1>)
    
        ''//Add some some paragraphs
        For J As Integer = 1 To 100
            sampleHTML.Add(<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.
                              Suspendisse ac arcu porta, tempor justo eu, tincidunt eros.
                              Integer lorem dolor, pretium sit amet vehicula dapibus,
                              faucibus a tellus.</p>)
        Next
    Next
    
    ''//This will be our collection of chapter numbers and the actual page numbers that they correspond to.
    Dim PageNumbers As New Dictionary(Of String, Integer)
    
    ''//Standard PDF setup here, nothing special
    Using fs As New FileStream(TestFile, FileMode.Create, FileAccess.Write, FileShare.None)
        Using doc As New Document()
            Using writer = PdfWriter.GetInstance(doc, fs)
                doc.Open()
    
                ''//Parse our HTML
                Dim htmlarraylistBody = iTextSharp.text.html.simpleparser.HTMLWorker.ParseToList(New StringReader(sampleHTML.ToString()), Nothing)
    
                ''//Loop through each item
                For Each Elem In htmlarraylistBody
    
                    ''//Some HTML elements freak the system out so you should check if they are content first.
                    If Elem.IsContent() Then
    
                        ''//If the current element is a paragraph and start with our flag value
                        If (TypeOf Elem Is Paragraph) AndAlso DirectCast(Elem, Paragraph).Content.StartsWith(FlagValue) Then
    
                            ''//Add that to our master collection but DO NOT write it to the PDF
                            PageNumbers.Add(DirectCast(Elem, Paragraph).Content.Replace(FlagValue, ""), writer.PageNumber)
                        Else
    
                            ''//Otherwise just write to the PDF normally
                            doc.Add(Elem)
                        End If
                    End If
                Next
    
                doc.Close()
            End Using
        End Using
    End Using
    

    【讨论】:

    • 我非常感谢克里斯的详细回复!我会试一试的!
    • @AmberHart28:你应该支持这个答案。太棒了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 2018-04-06
    • 1970-01-01
    • 2014-04-15
    • 1970-01-01
    • 2015-03-11
    • 1970-01-01
    相关资源
    最近更新 更多