دليل: فتح المستندات باستخدام عارض Doconut المدمج في .NET 8
← Back to Blog••4 min read

دليل: فتح المستندات باستخدام عارض Doconut المدمج في .NET 8

المقدمة

قد تقوم أمثلة Doconut القديمة بإنشاء Viewer مباشرةً باستخدام وسائط الذاكرة المؤقتة، وسياق HTTP، ومسار الترخيص. هذا ليس نموذج التكامل الحالي في .NET 8. تقوم AddDoconut() بتسجيل Viewer عبر حقن الاعتماديات، وتستقبل نقاط النهاية في التطبيق الخدمة بدلاً من استدعاء المُنشئ.

مكونات الخادم المجردة التي تمرر رمز جلسة غير شفاف إلى سطح عرض المستند
مكونات الخادم المجردة التي تمرر رمز جلسة غير شفاف إلى سطح عرض المستند

هذه الدورة التعليمية تتبع تدفق الطلب الحالي: تسجيل الخدمات والوسيط، إصدار موارد العارض المدمجة، فتح مستند باستخدام OpenDocumentAsync، إرجاع رمز غير شفاف، وتمرير ذلك الرمز إلى عنصر المتصفح.


1. تثبيت وتسجيل Doconut

أضف حزمة .NET 8:

dotnet add package Doconut.NET8

سجِّل Doconut وخدمات جلسة ASP.NET:

builder.Services.AddDoconut(options =>
{
    options.LicensePath = "Doconut.Viewer.lic";
    options.MiddlewarePath = "/doconut";
    options.ResourcesPath = "/doconut-res";
    options.UnsafeMode = false;
});

builder.Services.AddSession();

قم بربط middleware بالترتيب المطلوب. يجب أن يعمل middleware الخاص بالموارد قبل middleware المستند النهائي:

app.UseRouting();
app.UseSession();
app.UseDoconutResources();
app.Map("/doconut", branch => branch.UseDoconut());

MiddlewarePath ينسق الإعدادات لكنه لا ينشئ فرع ASP.NET بنفسه. يجب أن يتطابق المسار /doconut المُعيّن مع BasePath الخاص بالعنصر.

2. إضافة سطح العرض والموارد

عارض المتصفح Doconut هو مكوّن jQuery. في صفحة Razor، قم بحقن Viewer واطلب منه إصدار وسوم الموارد بترتيب الاعتماديات:

@inject Doconut.Viewer Viewer

@Html.Raw(Viewer.ReferenceCss(new CssConfig
{
    IncludeViewerCss = true
}))

@Html.Raw(Viewer.ReferenceScripts(new ScriptConfig
{
    IncludeJQuery = true,
    IncludeViewerScripts = true
}))

<div id="divDocViewer">
    <div id="div_ctlDoc"></div>
</div>

قم بتهيئة العنصر بالمسارات التي تتطابق مع تسجيل الخادم:

const objViewer = $('#div_ctlDoc').docViewer({
    showThumbs: true,
    autoLoad: false,
    pageZoom: 100,
    FitType: 'width',
    BasePath: '/doconut',
    ResPath: '/doconut-res/images',
    onError: function (message) {
        console.error('Doconut viewer error:', message);
    }
});

حساسية حالة الأحرف في الخيارات مهمة. استخدم الأسماء المعروضة من قبل النسخة المثبتة بدلاً من توحيدها إلى نمط واحد.

3. حقن Viewer وفتح مستند

Viewer مسجَّل كخدمة مؤقتة. احصل عليه عبر حقن نقطة النهاية، أو حقن المُنشئ، أو الطريقة المكافئة في تطبيق ASP.NET Core الخاص بك.

app.MapPost("/api/open", async (
    Viewer viewer,
    CancellationToken ct) =>
{
    string token = await viewer.OpenDocumentAsync(
        "wwwroot/files/Sample.pdf",
        ct: ct);

    return Results.Ok(new { token });
});

لرفع ملف، قدم تدفقًا (stream) وFileInfo يحدد امتداد الملف المصدر:

app.MapPost("/api/open-upload", async (
    IFormFile file,
    Viewer viewer,
    CancellationToken ct) =>
{
    await using var stream = file.OpenReadStream();
    string token = await viewer.OpenDocumentAsync(
        stream,
        new FileInfo(file.FileName),
        ct: ct);

    return Results.Ok(new { token });
});

تحقق من حجم الرفع، والامتداد، والتفويض قبل فتح المحتوى المقدم من المستخدم. لا تحول اسم الملف المرسل إلى مسار على الخادم.

4. تمرير الرمز إلى العنصر

احصل على نقطة النهاية المفتوحة ومرّر الرمز المسترجع إلى objViewer.View:

fetch('/api/open', { method: 'POST' })
    .then(response => {
        if (!response.ok) throw new Error('The document could not be opened.');
        return response.json();
    })
    .then(data => objViewer.View(data.token))
    .catch(error => console.error(error));

عامل الرمز كبيانات اعتماد حاملة لجلسة مستند حية:

  • لا تقم بتسجيله أو حفظه.
  • أرجعه فقط إلى عميل مخوّل.
  • لا تكشف عن مسار الملف المصدر.
  • أعد فتح المستند عندما تنتهي صلاحية الجلسة.
  • أغلق الجلسة عندما لا يكون المستند مطلوبًا بعد الآن.

5. إغلاق جلسات الخادم عن عمد

يمكن لكود العميل استدعاء objViewer.Close() عندما يغادر المستخدم العارض. يمكن لتدفقات العمل على الخادم أيضًا إلغاء رمز معروف صراحةً:

app.MapPost("/api/close", (string token, Viewer viewer) =>
{
    viewer.CloseDocument(token);
    return Results.NoContent();
});

الإغلاق الصريح مفيد خصوصًا للمستندات الكبيرة. يبقى انتهاء صلاحية الجلسة كحل احتياطي، وليس بديلاً لإدارة دورة حياة التطبيق المتوقعة.

6. إضافة الوحدات الاختيارية فقط بعد عمل النواة

تُرفق البحث والتعليقات على نفس العارض المُهيأ. أضف ملفات CSS، والسكريبتات، والربط، وفحوصات الترخيص، واستدعاءات دورة الحياة الخاصة بها فقط بعد نجاح التدفق الأساسي:

AddDoconut + session services
    -> UseSession
    -> UseDoconutResources
    -> mapped UseDoconut branch
    -> viewer resources and mount
    -> initialize docViewer
    -> OpenDocumentAsync
    -> objViewer.View(token)

هذا الترتيب يحافظ على فصل فشل العرض الأساسي عن تكوين الوحدات الاختيارية.

أخطاء الترحيل الشائعة

النمط القديم أو غير الصحيحالاتجاه الحالي في .NET 8
new Viewer(cache, accessor, licensePath)حقن Viewer بعد AddDoconut()
استدعاءات تحميل الترخيص الثابتة في كود الطلبتكوين إدخال الترخيص في AddDoconut()
أمثلة OpenDocument(...) المتزامنةاستخدام OpenDocumentAsync(...)
شبكة توصيل محتوى (CDN) للعارض خارجية أو مختلقةإصدار الموارد المدمجة باستخدام ReferenceCss و ReferenceScripts
واجهة برمجة تطبيقات JavaScript العامة init()تهيئة $('#div_ctlDoc').docViewer(...)
حفظ رمز العارضاحفظ معرّف المستند الخاص بك؛ عامل الرمز كعنصر مؤقت

استخدم توثيق Doconut الرسمي وتحقق من الأمثلة مقابل نسخة الحزمة المثبتة قبل تعديلها لتناسب كود الإنتاج.

#Doconut#.NET 8#عارض المستندات#ASP.NET Core#JavaScript