جستجو

جستجوی متنی بومی در ترکیب Viewer

Doconut Viewer جستجوی معمولی را با استفاده از متنی که توسط نمایشگر فرمت استخراج می‌شود یا یک تغییر مسیر PDF مبتنی بر متن فراهم می‌کند. این قابلیت نیاز به مجوز Search دارد.

فعال‌سازی رابط کاربری جستجو

جستجو یک ماژول Viewer است، نه یک نوار ابزار مستقل. صفحه کامل باید شامل منابع Viewer، نوار ابزار Viewer، محل نصب Viewer و objViewer مقداردهی اولیه شده باشد؛ سپس ریبان جستجو نصب و به همان نمونه متصل می‌شود.

جستجو و حاشیه‌نویسی ویژگی‌های دارای مجوز داخلی هستند، نه بسته‌های AddPlugin<T>(). منابع جستجو را از Viewer درخواست کنید؛ برچسب‌های آن‌ها فقط زمانی صادر می‌شوند که مجوز جستجو را بدهد. نماهای 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، مقادیر مشابه را از کد‑پشت در دسترس قرار داده و با <%= %> بنویسید.

ریبان جاسازی‌شده همان متدهای JavaScript موجود برای یک رابط کاربری سفارشی را فراخوانی می‌کند.

ترکیب کامل Viewer را در نشانه‌گذاری قابل مشاهده نگه دارید، ابتدا docViewer را مقداردهی اولیه کنید و سپس ریبان دارای مجوز را متصل کنید:

html
<nav id="toolbar" aria-label="Document viewer controls">
    <!-- Viewer controls, including the button that opens Search -->
</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)ارسال پیام وضعیت از طریق callback پیکربندی‌شده

Callback اختیاری onToggle(isOpen) به میزبان امکان همگام‌سازی دکمه جستجوی خود را می‌دهد و onLayout به آن اجازه می‌دهد هنگام تغییر ارتفاع ریبان، Viewer را دوباره اندازه‌گیری/تنظیم کند. برای توالی راه‌اندازی ترکیبی Viewer، Search و Annotation، به شروع سریع مراجعه کنید.

جستجو از جاوااسکریپت

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 پاسخ می‌دهد. به‌جای تجزیهٔ دستی آن پاسخ داخلی، از API ویجت استفاده کنید.

بررسی قابلیت جستجو

پاسخ اولیه گزارش می‌دهد:

text
X-Doconut-Can-Search: 1

پس از مقداردهی اولیه، objViewer.CanSearch() همان verdict فرمت/نشست را نشان می‌دهد. وقتی سرور 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، ایمیل، 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

یک مجوز موقت/دموی فعال، جستجو را در دوره فعال خود اعطا می‌کند. عدم وجود مجوز و فایل قدیمی TRIAL هیچ قابلیت جستجویی را اعطا نمی‌کند. بدون جستجو:

  • ReferenceCss و ReferenceScripts بسته‌های جستجو را حذف می‌کنند.
  • DocImage.axd درخواست‌های جستجو را رد می‌کند به‌جای برگرداندن نتایج.

قابلیت نمایش UI سفارشی را از IDoconutLicenseService.IsCapabilityGranted(LicenseCapability.Search) کنترل کنید و برای verdict جداگانهٔ فرمت/نشست از CanSearch() استفاده کنید.

عیب‌یابی

علائمبررسی
نوار جستجو موجود نیستقابلیت جستجو و IncludeSearchCss/IncludeSearchScripts/IncludeSearchBar
CanSearch() برابر false استنمایشگر فرمت، مسیر DefaultRender انتخاب‌شده، و هدر پاسخ مقداردهی اولیه
جستجو برای یک PDF اسکن‌شده صفر برمی‌گرداندسند لایهٔ متنی ندارد؛ از منبع متنی استفاده کنید یا یک پروجکشن PDF که متن را حفظ می‌کند
جستجو کار می‌کند اما برجسته‌سازی‌ها جابجا هستندمسیر رندر، وضوح، تبدیلات سند، و جعبه‌های کلمه استخراج‌شده

آیا این صفحه مفید بود؟