搜索

在 Viewer 组合中的原生文本搜索

Doconut Viewer 提供常规搜索,使用格式查看器提取的文本或基于文本的 PDF 重定向。它需要 Search 许可证功能。

启用搜索 UI

Search 是 Viewer 的一个模块,而不是独立的工具栏。完整页面必须包含 Viewer 资源、Viewer 工具栏、Viewer 挂载点以及已初始化的 objViewer;随后会挂载并将 Search 功能区附加到同一实例上。

Search 和 annotation 是内置的许可功能,而非 AddPlugin<T>() 包。向 Viewer 请求搜索资源;只有在许可证授予 Search 时才会输出相应的标签。MVC 5 视图没有 @inject,因此在控制器中构建标签并通过 ViewBag 传递,同时传递页面所需的许可证标志:

csharp
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
ViewBag.ViewerCss = viewer.ReferenceCss(new CssConfig
{
    IncludeViewerCss = true,
    IncludeSearchCss = true
});
ViewBag.ViewerScripts = viewer.ReferenceScripts(new ScriptConfig
{
    IncludeJQuery        = true,
    IncludeViewerScripts = true,
    IncludeSearchScripts = true,
    IncludeSearchBar     = true
});
ViewBag.IsSearchEnabled = viewer.IsSearchEnabled;

在视图中使用 @Html.Raw(ViewBag.ViewerCss) 和 @Html.Raw(ViewBag.ViewerScripts) 写入它们。在 Web Forms 中,从代码后置文件中公开相同的值,并使用 <%= %> 写入。

嵌入的功能区调用与自定义 UI 相同的 JavaScript 方法。

在标记中保持完整的 Viewer 组合可见,首先初始化 docViewer,然后附加已授权的功能区:

html
<nav id="toolbar" aria-label="Document viewer controls">
    <!-- 查看器控件,包括打开搜索的按钮 -->
</nav>
<div id="searchBarMount"></div>
<div id="divDocViewer"><div id="div_ctlDoc"></div></div>

<script>
    let searchBar = null;
    let currentToken = '';

    const objViewer = $('#div_ctlDoc').docViewer({
        BasePath: '/',
        ResPath: 'doconut-res/images'
    });

    @if ((bool)ViewBag.IsSearchEnabled)
    {
        <text>
    searchBar = $('#searchBarMount').doconutSearchBar({
        docId: 'ctlDoc',
        getRequestParams: () => ({ token: currentToken }),
        onStatus: (message) => console.log(message),
        onToast: (message, type) => console.log(type, message),
        onLayout: () => requestAnimationFrame(() => objViewer.Refit())
    });
    searchBar.attach(objViewer);
        </text>
    }
</script>

服务器端的 if 很重要:如果没有 Search 功能,ReferenceScripts 会省略功能区的脚本,因此未加保护的 doconutSearchBar(...) 调用会抛出错误并导致 Viewer 页面无法启动。在 Web Forms 中,使用 <% if (IsSearchEnabled) { %> … <% } %> 编写相同的保护。

该组件注入 Find、Options 和 Results 组,并处理搜索、清除、匹配计数以及上一条/下一条匹配的导航。托管的 Viewer 工具栏只需切换它即可:

javascript
searchBar.isOpen() ? searchBar.close() : searchBar.open();

它的公共 API 故意保持简洁:

方法用途
attach(objViewer)将功能区连接到已初始化的 viewer;仅需一次
open() / close()显示或隐藏功能区;关闭时还会清除高亮
reset()清除当前搜索词、结果计数和高亮
isOpen()报告功能区是否可见
setStatus(message)通过配置的回调转发状态消息

可选的 onToggle(isOpen) 回调允许宿主同步其 Search 按钮,onLayout 回调则在功能区高度变化时让其调整/重新适配 viewer。有关 Viewer、Search 和 Annotation 的组合启动顺序,请参见 快速入门。

从 JavaScript 搜索

javascript
objViewer.Search(keyword, false, function (resultCount) {
    console.log('Matches:', resultCount);
});

第二个参数表示全字/精确匹配。匹配数量在回调中返回:Search 本身会向服务器请求但不返回有用的数据,所以 var n = objViewer.Search(keyword, false) 总是得到 undefined —— 这样构建的页面会显示“未找到”,而查看器会高亮匹配项。回调之后:

方法结果
SearchMatchCount()文档中所有单独匹配的总数。
SearchSummary(false)返回 [pageNumber, matchCount] 条目,不进行重新绘制。
SearchSummary(true)相同的摘要,并绘制页面/缩略图高亮。
GotoSearchMatch(index)跳转到基于零的匹配索引。

DocImage.axd 会响应 search=<term> 和 exact=true|false 并返回 XML。请使用 widget API,而不是自行解析内部响应。

检查搜索功能

初始化响应报告:

text
X-Doconut-Can-Search: 1

初始化后,objViewer.CanSearch() 会给出相同的格式/会话判断。当服务器返回 0 时返回 false;在收到响应之前,或使用省略该头的旧服务器时,默认返回 true。

三个独立的判断点不应混淆:

门问题
CanSearch() / response header已解析的查看器是否具有原生索引/搜索路径?
AllowSearch此格式配置请求文本提取时,开关是否存在?
LicenseCapability.Search应用程序是否被授权执行搜索并接收 UI 包?

一种格式在技术上可以支持搜索,但当前许可证可能禁止此操作。

为每种格式启用提取

csharp
var token = await viewer.OpenDocumentAsync(path, new PdfConfig
{
    AllowSearch = true,
    AllowCopy   = true   // optional: lets the user drag a region and copy its text
});

AllowSearch 和 AllowCopy 存在于 PdfConfig、WordConfig、ExcelConfig 和 PptConfig 中。Office 系列属性会委托给其内部的 PdfConfig。两者默认均为 false。

常规的原生搜索适配器支持 PDF、Word、Excel、PowerPoint、TXT、Visio、email、EPUB 和 MHT。XPS 默认使用其 PDF 路径。HTML 和 Microsoft Project 可受益于基于文本的 PDF 重定向:

csharp
// DefaultRender = false → converted to a text-based PDF → searchable
var token = await viewer.OpenDocumentAsync(path, new HtmlConfig { DefaultRender = false });

对于原生渲染器,CanSearch() 描述查看器的能力;它并不保证特定文档包含可用的文本。页面仅为扫描图像的 PDF 仍可能返回零原生结果。

正常搜索行为

服务器按以下顺序尝试搜索来源:

  1. 原生 ISearchableViewer 结果。
  2. 预构建的 .srh 搜索索引。
  3. 当不存在搜索源时返回错误/空结果。

即使 CanSearch() 为 true,若特定文档没有文本层,也会返回零匹配。

许可和 UI 行为

活动的 Temporary/Demo 许可证在其有效期内授予搜索功能。缺少许可证或使用旧的 TRIAL 文件则不提供搜索能力。没有搜索时:

  • ReferenceCss 和 ReferenceScripts 会省略搜索相关的资源包。
  • DocImage.axd 拒绝搜索请求,而不是返回结果。

通过 IDoconutLicenseService.IsCapabilityGranted(LicenseCapability.Search) 控制自定义 UI 的可见性,并使用 CanSearch() 获取格式/会话的单独判断。

故障排除

症状检查
搜索栏缺失检查搜索功能以及 IncludeSearchCss/IncludeSearchScripts/IncludeSearchBar 是否已包含。
CanSearch() 为 false检查格式查看器、所选的 DefaultRender 路径以及初始化响应头。
扫描的 PDF 返回零结果文档没有文本层;请使用包含文本的来源或保留文本的 PDF 投影。
搜索可用但高亮位置偏移检查渲染路径、分辨率、文档变换以及提取的单词框。

此页面对您有帮助吗?