以编程方式捕获 .PDF 文件中所有嵌入文本项的位置和内容?

Posted

技术标签:

【中文标题】以编程方式捕获 .PDF 文件中所有嵌入文本项的位置和内容?【英文标题】:Programmatically capture the location & content of all embedded text items within a .PDF file? 【发布时间】:2016-01-11 22:13:56 【问题描述】:

我有一系列 .pdf 文档,其中包含许多单独的嵌入文本实例,我需要能够遍历每个实例并以编程方式捕获两件事:(1) 轮廓矩形的大小和位置每个文本实例和 (2) 每个矩形内的实际文本本身。

这里的目标是能够使用 JS 在每个文本项的顶部自动插入一个按钮。我需要能够为每个按钮提供与现有文本矩形(至少大致)对应的形状/大小和位置,并且我需要将每个按钮命名为每个矩形中包含的确切文本字符串。

这样的事情用JS能做到吗?看起来应该是可能的,但我绝对没有足够的 JS 来实际做到这一点。

我使用的 .pdf 文件都是建筑平面图,嵌入文本的每个实例都是每个楼层内特定房间的房间号,如下所示:

我有工作 JS 代码来创建任意按钮循环(假设我有一组矩形定义和文本/名称可用于大小、位置和名称),但我不知道如何以编程方式引用到每个嵌入的文本项——既不是文本矩形的大小/位置,也不是文本本身的内容。

似乎没有一个方便的函数可以遍历文档中嵌入文本的所有实例,并捕获相关信息,就像我可以使用另一个对象(例如,超链接使用 getLinks 命令)。

这是实施大型项目的最后一步,手动创建每个按钮是不切实际的,因为全套平面图需要数千个按钮。

【问题讨论】:

您是否要在 PDF 文件中插入按钮?您是通过将 PDF 嵌入到浏览器窗口中来显示 PDF,如果是这样,这不需要插件还是您首先在浏览器窗口中渲染 PDF? @thril 我想到的是在 pdf 文件中插入按钮,所以我所描绘的是一个可以/可以完全在 Acrobat 中运行的解决方案,例如。尽管在整个项目的最终实现中,.pdf 文件通常会从 Excel 用户窗体的网络浏览器控件中打开。因此,如果有任何解决方案需要与浏览器交互,听起来这也是一种可能。感谢您的回复。 由于您使用的是 Excel,您可以很好地与 VBA 集成,或者在最坏的情况下在 .net 中创建一个库并使用 VBA 中的库。 Web 端只需要促进通信。除了网络视图之外,您是否探索过其他选项? @thril 我实际上认为自己对 VBA 几乎是半精通,但到目前为止,我基本上没有运气让 VBA 识别或操作 .pdf 文件中基于 JS 的控件。我确定我只是不知道我需要开始使用的粗略命令,但是在这种情况下我没有成功让 JS 和 VBA 很好地协同工作。 【参考方案1】:

在客户端,您只能显示 html 内容。

PDFJS (https://mozilla.github.io/pdf.js/web/viewer.html) 是一个 javascript 库,可以用作 PDF 的 javascript“查看器”,也可以理解 PDF 的本质。随意使用它并将其扩展为您的需求(使区域交互左右..)

您也可以尝试在服务器端将 pdf 渲染为图像(例如使用 xpdf pdftopng),然后使用 pdf “tokenizer”(例如 http://www.unixuser.org/~euske/python/pdfminer/index.html )并在原始图片顶部显示交互区域

【讨论】:

PDF.js 具有 getTextContent 调用,可让您提取所有文本项 (github.com/mozilla/pdf.js/blob/master/src/display/api.js#L1058)。另请参阅github.com/mozilla/pdf.js/blob/master/examples/text-only/… 示例 感谢大家的回复。目前,看起来很有希望我将能够使用 getTextContent 来实现我在这种情况下需要做的事情。如果/当我成功时会报告。【参考方案2】:

据我所知,要执行您想要的操作,必须在服务器端 Linux/Windows 或桌面应用程序中完成。最简单的方法是将您的页面呈现为图像,并在这些图像之上使用 HTML 进行任何交互式覆盖。听起来你想做的事只能使用比 Web JS / HTML 库提供的更强大的语言来完成。

有强大的 Java 和 .NET 库可以处理 PDF 并完成此任务。一个好的开源是http://sourceforge.net/projects/itextsharp/

还有更强大的不是免费的,例如:https://www.foxitsoftware.com/products/sdk/net-sdk/

您可以编写一个服务,该服务接受一个输入 PDF 并将每页的图像以及每页的图像路径、坐标和标题输出到 JSON 文件中。然后在 HTML/JS 中将 JSON 加载到对象数组中并循环插入图像,并根据需要使用鼠标悬停或 <a> 链接将image-map 应用于它们。

【讨论】:

【参考方案3】:

您可以使用 HiQPdf 库以编程方式搜索 PDF 中的文本。您可以在Search Text In PDF blog page 中找到更多详细信息和代码示例。代码示例是:

// get the PDF file
string pdfFile = Server.MapPath("~") + @"\DemoFiles\Pdf\InputPdf.pdf";

// get the text to search
string textToSearch = textBoxTextToSearch.Text;

// create the PDF text extractor
PdfTextExtract pdfTextExtract = new PdfTextExtract();

int fromPdfPageNumber = int.Parse(textBoxFromPage.Text);
int toPdfPageNumber = textBoxToPage.Text.Length > 0 ? int.Parse(textBoxToPage.Text) : 0;

// search the text in PDF document
PdfTextSearchItem[] searchTextInstances = pdfTextExtract.SearchText(pdfFile, textToSearch,
            fromPdfPageNumber, toPdfPageNumber, checkBoxMatchCase.Checked, checkBoxMatchWholeWord.Checked);

// load the PDF file to highlight the searched text
PdfDocument pdfDocument = PdfDocument.FromFile(pdfFile);

// highlight the searched text in PDF document
foreach (PdfTextSearchItem searchTextInstance in searchTextInstances)

    PdfRectangle pdfRectangle = new PdfRectangle(searchTextInstance.BoundingRectangle);

    // set rectangle color and opacity
    pdfRectangle.BackColor = Color.Yellow;
    pdfRectangle.Opacity = 30;

    // highlight the text
    pdfDocument.Pages[searchTextInstance.PdfPageNumber - 1].Layout(pdfRectangle);


// write the modified PDF document
try

    // write the PDF document to a memory buffer
    byte[] pdfBuffer = pdfDocument.WriteToMemory();

    // inform the browser about the binary data format
    HttpContext.Current.Response.AddHeader("Content-Type", "application/pdf");

    // let the browser know how to open the PDF document and the file name
    HttpContext.Current.Response.AddHeader("Content-Disposition", String.Format("attachment; filename=SearchText.pdf; size=0",
                pdfBuffer.Length.ToString()));

    // write the PDF buffer to HTTP response
    HttpContext.Current.Response.BinaryWrite(pdfBuffer);

    // call End() method of HTTP response to stop ASP.NET page processing
    HttpContext.Current.Response.End();

finally

    pdfDocument.Close();

【讨论】:

【参考方案4】:

我实际上已经能够使用原生 Acrobat Javascript 中的 getPageNthWord 和 getPageNthWordQuads 命令完成我需要做的事情,并且不需要求助于 PDF.js 或任何其他语言或库。在我的例子中,还需要使用 Matrix2D 函数在“quad”(用于捕获每个单词的位置和维度)和“rect”(用于定义新按钮的空间和位置)语法之间进行转换。

【讨论】:

以上是关于以编程方式捕获 .PDF 文件中所有嵌入文本项的位置和内容?的主要内容,如果未能解决你的问题,请参考以下文章

如何替换或修改嵌入在 PDF 文件中的字体或字形?

如何以特定格式以编程方式创建pdf?

如何在现有 PDF 中嵌入字体?

如何从 PDF 中提取嵌入字体作为有效字体文件?

如何在 C# 中以编程方式搜索 PDF 文档 [关闭]

以编程方式将 Word (docx) 转换为 PDF