البدء السريع
اعرض مستندك الأول في دقائق
هذا الدليل يأخذ تطبيق ASP.NET Core من ملف Program.cs فارغ إلى مستند يُعرض في المتصفح: تسجيل الخادم، حزمة المشاهد الكاملة (شريط أدوات المشاهد، تثبيت المشاهد، وأشرطة البحث/التعليق الاختيارية)، مراجع الأصول، تهيئة العميل، فتح المستند، والتنفيذ.
إعداد الخادم
AddDoconut() يسجل الخدمات؛ UseDoconutResources() و UseDoconut() يربطان الوسيط. يجب أن يأتي استدعاء الموارد أولاً. استدعاءات الجلسة مطلوبة أيضاً — أمان المستند الافتراضي في Doconut يتحقق من كل طلب صفحة مقابل حالة جلسة ASP.NET. هل قمت بتسجيل Doconut مسبقاً خلال التثبيت؟ تخطّ إلى القسم التالي.
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
});
builder.Services.AddSession(); // Doconut document security rides on ASP.NET session state
app.UseSession(); // call UseSession() before UseDoconut()
app.UseDoconutResources(); // must be registered before UseDoconut()
app.UseDoconut();لترتيب مسارات نمط الإنتاج، قم بربط وسيط المستند إلى فرع صريح واحافظ على توافق إعدادات المسارات الأربعة:
builder.Services.AddDoconut(options =>
{
options.LicensePath = Path.Combine(AppContext.BaseDirectory, "Doconut.Viewer.lic");
options.MiddlewarePath = "/doconut";
options.ResourcesPath = "/doconut-res";
options.UnsafeMode = false;
});
builder.Services.AddSession();
app.UseRouting();
app.UseSession();
app.UseDoconutResources();
app.Map("/doconut", branch => branch.UseDoconut());MiddlewarePath هو قيمة تنسيق؛ لا يقوم بإنشاء فرع ASP.NET Core بحد ذاته. في هذا المثال يقوم المضيف بربط /doconut، لذا يجب على العميل استخدام BasePath: '/doconut'. ResourcesPath يخدم الحزمة المدمجة على /doconut-res، وبالتالي يكون مسار موارد صورة الودجت ResPath: '/doconut-res/images'.
إضافة المشاهد إلى صفحة
المشاهد هو القلب المطلوب للصفحة. سطح عرضه يستخدم عنصرين div متداخلين:
<div id="divDocViewer">
<div id="div_ctlDoc"></div>
</div>عامل شريط الأدوات، تثبيت الوحدات، وسطح المشاهد كأنهما تركيبة صفحة واحدة. يدمج البحث والتعليق أشرطةهما المدمجة في تثبيتات اختيارية، لكن هذه الوحدات لا تعمل بشكل مستقل أبداً: فهي دائماً تُرفق بالمشاهد في نفس الصفحة. استخدم نفس الترتيب كما في Doconut.TestApp و Doconut.TestApp.Distributed:
<nav id="toolbar" aria-label="Document viewer controls">
<!-- Viewer navigation, zoom, Search, and Annotation buttons -->
</nav>
<div id="searchBarMount"></div>
<div id="annBarMount"></div>
<div id="divDocViewer">
<div id="div_ctlDoc"></div>
</div>الإشارة إلى أصول المشاهد
في عرض Razor، تُدرج خدمة Viewer المُحقنة وسوم <link> و <script> الخاصة بالمشاهد بترتيب الاعتمادية — الودجت هو إضافة jQuery، لذا يجب تحميل jQuery قبل سكريبتات المشاهد:
@inject Doconut.Viewer Viewer
@Html.Raw(Viewer.ReferenceCss(new CssConfig
{
IncludeBootstrapCss = true,
IncludeViewerCss = true
}))
@Html.Raw(Viewer.ReferenceScripts(new ScriptConfig
{
IncludeJQuery = true,
IncludeBootstrap = true,
IncludeViewerScripts = true
}))للحصول على حزمة المشاهد الكاملة، اطلب موارد المشاهد والوحدات معاً:
@Html.Raw(Viewer.ReferenceCss(new CssConfig
{
IncludeBootstrapCss = true,
IncludeViewerCss = true,
IncludeSearchCss = true,
IncludeAnnotationCss = true
}))
@Html.Raw(Viewer.ReferenceScripts(new ScriptConfig
{
IncludeJQuery = true,
IncludeBootstrap = true,
IncludeViewerScripts = true,
IncludeSearchScripts = true,
IncludeSearchBar = true,
IncludeAnnotationScripts = true,
IncludeAnnotationBar = true
}))IncludeViewerCss و IncludeViewerScripts هما العلامتان الأساسيتان. لا تنشر مثال شريط بحث أو تعليق دونهما، ولا تثبيت المشاهد، ولا مثال docViewer. تتجاهل ReferenceCss و ReferenceScripts موارد الوحدة الاختيارية عندما لا تمنح الرخصة الحالية تلك القدرة؛ يظل المشاهد الأساسي يعمل.
تهيئة المشاهد
الودجت على جانب العميل هو إضافة jQuery. هذه مجموعة الحد الأدنى من خيارات التهيئة الفعلية (ليس كودًا تمثيليًا):
let searchBar = null;
let annBar = null;
const objViewer = $('#div_ctlDoc').docViewer({
showThumbs: true,
autoLoad: false,
pageZoom: 100,
FitType: 'width',
BasePath: '/doconut',
ResPath: '/doconut-res/images',
onViewerReady: function () {
// pages are visible; safe to hide a loading spinner here
},
// Forward annotation lifecycle events to the embedded ribbon when it is present.
onAnnLoaded: () => annBar?.handleAnnLoaded(),
onAnnSaved: () => annBar?.handleAnnSaved(),
onAnnSaveError: () => annBar?.handleAnnSaveError(),
onAnnClosed: () => annBar?.handleAnnClosed(),
onError: function (message) {
console.error('Doconut viewer error:', message);
}
});حساسية الأحرف في الخيارات مختلطة حقًا — showThumbs، autoLoad، و pageZoom هي camelCase، بينما FitType، BasePath، و ResPath هي PascalCase. لا توجد قاعدة ثابتة؛ إذا أخطأت في كتابة الحالة سيتم تجاهل الخيار صامتًا (يتراجع الودجت إلى الإعداد الافتراضي بدلاً من إلقاء خطأ).
تجميع حزمة المشاهد الكاملة
كل من تطبيقات المرجع .NET 6 تثبت الأجزاء التالية معًا في صفحة واحدة:
| جزء من الحزمة | المتطلبات | طريقة الاتصال |
|---|---|---|
موارد المشاهد، التثبيت، و objViewer | مطلوب | محرك عرض المستند الأساسي |
| شريط أدوات المشاهد | مطلوب في تركيبة المرجع | علامات HTML للمضيف؛ الأزرار تستدعي نفس objViewer |
| شريط بحث | اختياري، وحدة مرخصة | doconutSearchBar(...).attach(objViewer) |
| شريط تعليقات | اختياري، وحدة مرخصة | doconutAnnotationBar(...).attach(objViewer) |
على الرغم من أن شريط أدوات المشاهد الرئيسي هو علامة HTML للمضيف، فإنه يُثبت جنبًا إلى جنب مع المشاهد ولا يجب توثيقه كعنصر مستقل. هذا يحافظ على تخطيطه، تسمياته، أيقوناته، وقواعد التفويض تحت سيطرة تطبيقك بينما كل زر يتحكم في نفس نسخة المشاهد:
<nav id="toolbar" aria-label="Document viewer controls">
<button type="button" onclick="objViewer.GotoPage(1)">First</button>
<button type="button" onclick="objViewer.Next(false)">Previous</button>
<button type="button" onclick="objViewer.Next(true)">Next</button>
<button type="button" onclick="objViewer.GotoPage(objViewer.TotalPages())">Last</button>
<button type="button" onclick="objViewer.Zoom(false)">Zoom out</button>
<button type="button" onclick="objViewer.Zoom(true)">Zoom in</button>
<button type="button" onclick="objViewer.FitType('width')">Fit width</button>
<button type="button" onclick="objViewer.FitType('height')">Fit height</button>
<button type="button" id="openSearch">Search</button>
<button type="button" id="openAnnotations">Annotations</button>
</nav>الشريط المرجعي الكامل ينسخ أيضًا wwwroot/js/viewerToolbar.js إلى تطبيق المضيف لتوفير وظائف الدوران، المصغرات، الطباعة، ملء الشاشة، التخطيط، ومساعدي حالة الأزرار. حمّل هذا الملف بعد Viewer.ReferenceScripts(...). احتفظ بالمساعد وعلامة <nav id="toolbar"> معًا عند نسخ تنفيذ العرض الكامل.
حافظ على ترتيب تهيئة الحزمة كما هو مستخدم في كلا تطبيقي المرجع:
- إصدَر CSS للمشاهد والوحدات المرخصة.
- عرض شريط أدوات المشاهد، تثبيتات البحث/التعليق، وتثبيت المشاهد معًا.
- إصدَر سكريبتات للمشاهد والوحدات المرخصة.
- حمّل
viewerToolbar.jsالخاص بتطبيق المضيف. - ابدأ
docViewerواحتفظ بـobjViewerالناتج. - ابدأ كل شريط بحث أو تعليق مرخص.
- استدعِ
attach(objViewer)على كل شريط. - افتح المستند واحتفظ بالرمز المميز له لاستخدامه في المشاهد وطلبات الوحدات.
Doconut.TestApp.Distributed يحافظ على نفس تركيبة الواجهة المساعدة لشريط الأدوات. قيمة طلب access الإضافية وإعدادات إعادة المحاولة للعرض غير المتزامن تنتمي إلى النقل الموزع؛ لا تغير طريقة تجميع المشاهد أو شريط الأدوات أو الأشرطة.
الحراس على جانب الخادم مهمون: عندما تكون القدرة الاختيارية غير متوفرة، لا يُصدر سكريبتها، وبالتالي لا توجد دالة jQuery للوظيفة.
<script>
let currentToken = '';
const refitViewer = () =>
requestAnimationFrame(() => objViewer.Refit());
@if (Viewer.IsSearchEnabled)
{
<text>
searchBar = $('#searchBarMount').doconutSearchBar({
docId: 'ctlDoc',
getRequestParams: () => ({ token: currentToken }),
onLayout: refitViewer
});
searchBar.attach(objViewer);
</text>
}
@if (Viewer.IsAnnotationEnabled)
{
<text>
annBar = $('#annBarMount').doconutAnnotationBar({
docId: 'ctlDoc',
getRequestParams: () => ({ token: currentToken }),
onLayout: refitViewer
});
annBar.attach(objViewer);
</text>
}
document.getElementById('openSearch').addEventListener('click', () => {
if (!searchBar) return;
searchBar.isOpen() ? searchBar.close() : searchBar.open();
});
document.getElementById('openAnnotations').addEventListener('click', () => {
if (!annBar) return;
annBar.isOpen() ? annBar.close() : annBar.open();
});
</script>كل مكون مدمج يولد شريطه الخاص في DOM. يحتوي شريط البحث على مجموعات Find و Options و Results. يحتوي شريط التعليق على أدوات التأليف، عناصر التحكم في النمط، إجراءات الحفظ، وإجراءات تصدير/صورة اختيارية. تُظهر الأشرطة الدوال open(), close(), reset(), و isOpen()؛ يجب دائمًا استدعاء attach(objViewer) مرة واحدة بعد إنشائها.
المثال أعلاه يحذف استدعاءات المضيف الاختيارية ونقاط النهاية لتصدير/صورة التعليق لتقليل الإقلاع. راجع البحث والتعليقات لإعداد الميزات بالكامل، أو الثيمات المخصصة لتصميم أو استبدال شريط أدوات المشاهد المملوك للمضيف.
فتح مستند
الخادم يقدم نقطة نهاية واحدة: خدمة Viewer المُحقنة تفتح المستند وتُعيد رمز جلسة.
app.MapPost("/api/open", async (Viewer viewer) =>
{
// The token is opaque — hand it to the widget, never log or persist it.
string token = await viewer.OpenDocumentAsync("wwwroot/files/Sample.pdf");
return Results.Ok(new { token });
});العميل يجلب هذا الرمز ويقدمه للودجت عبر objViewer.View(token):
fetch('/api/open', { method: 'POST' })
.then(resp => resp.json())
.then(data => {
currentToken = data.token;
objViewer.View(currentToken);
});إغلاق المستند
استدعِ objViewer.Close() عندما يغادر المستخدم المشاهد أو يفتح مستندًا بديلاً. في سير عمل مدفوع من الخادم، viewer.CloseDocument(token) يزيل جلسة التخزين المؤقت فورًا، يُغلق محرك العرض، يحذف علامة الأمان، ويلغي الرمز المميز. انتهاء الصلاحية المتدرج يؤدي إلى نفس التنظيف في النهاية، لكن الإغلاق الصريح يُنصح به للمستندات الكبيرة.
تدفق الطلب المكتمل هو:
AddDoconut + middleware
-> render CSS/scripts and mount div
-> initialize docViewer
-> OpenDocumentAsync
-> return opaque token
-> objViewer.View(token)
-> page/search/annotation requests
-> Close / CloseDocumentعامل الرمز المميز كأنه اعتماد حامل: لا تُسجّله أبدًا، لا تُخزّنه، قدّمه فقط للودجت. هو يُعرّف جلسة مستند حية على الخادم ويتوقف عن العمل عندما تنتهي صلاحية الجلسة — أعد فتح المستند للحصول على رمز جديد.
تشغيله
ضع ملف PDF في wwwroot/files/Sample.pdf، شغّل dotnet run، وافتح الصفحة التي تستضيف الودجت. الصفحة الأولى تُعرض في المشاهد مع لوحة مصغرات على اليسار. إذا لم يحدث ذلك، راجع استكشاف الأخطاء وإصلاحها.
ما ستحصل عليه بدون ترخيص
غياب الترخيص لا يسبب استثناءً. المشاهد يُعرض كالمعتاد، لكن كل صفحة تحمل علامة مائية للتقييم. راجع إعداد الترخيص لمعرفة كيف يكتشف Doconut الترخيص وما يتغيّر بمجرد العثور عليه.
هل كانت هذه الصفحة مفيدة؟