نحوه کار Viewer

چرخهٔ درخواست سند

Doconut اسناد را به‌صورت تصاویر صفحه‌بندی‌شده که از طریق میدل‌ویر ASP.NET Core سرو می‌شوند، رندر می‌کند. درک چرخه حیات — باز کردن، توکن، درخواست‌های صفحه، بستن — تقریباً تمام رفتارهایی را که مشاهده می‌کنید، از جمله پیام‌های خطا، توضیح می‌دهد.

سه بخش متحرک

  • Viewer — سرویس عمومی که تزریق می‌کنید. اسناد را باز می‌کند و توکن‌های جلسه را برمی‌گرداند.
  • جلسهٔ سند — شیء سمت سرور که سند بارگذاری‌شده را نگه می‌دارد، با توکنی در IMemoryCache کلید می‌شود.
  • میان‌افزار Doconut — توسط UseDoconut() اضافه می‌شود؛ به هر درخواست که ویجت مرورگر می‌فرستد پاسخ می‌دهد و همیشه با توکن احراز می‌شود.

Viewer بدون حالت است — به‌صورت پیش‌فرض

Viewer sealed است، هیچ وضعیت سندی برای هر درخواست نگه نمی‌دارد و عمداً پیاده‌سازی IDisposable نمی‌کند. جلسات به‌صورت مستقل در مدیر جلسه زندگی می‌کنند و توسط انقضای کش یا CloseDocument(token) صریح پاک‌سازی می‌شوند.

در هر جایی که به آن نیاز دارید، تزریق کنید:

csharp
app.MapPost("/api/open", async (string fileName, Viewer viewer) =>
{
    var token = await viewer.OpenDocumentAsync($"files/{fileName}");
    return Results.Content(token, "text/plain");
});

چه اتفاقی در OpenDocumentAsync می‌افتد

  1. دروازه مجوز. یک مجوز رد شده یا منقضی شده (سیاه‌لیست‌شده، دست‌کاری‌شده، یا ساختی خارج از بازه به‌روزرسانی مجوز) بلافاصله LicenseException را پرتاب می‌کند، با دلیل رد به‌عنوان پیام — باز کردن هرگز به‌صورت خاموش برای یک مجوز نامعتبر (در مقابل غیاب) کاهش کیفیت نمی‌یابد. یک مجوز موقت یا اشتراکی که تاریخ‌اش منقضی شده است، استثنا نیست: آن پرتاب نمی‌کند — به‌جای آن به واترمارک کاهش می‌یابد.
  2. ایجاد جلسه. کارخانه viewer فرمت مناسب را بر اساس پسوند فایل انتخاب می‌کند و سند را بارگذاری می‌کند (به Rendering Pipeline مراجعه کنید). جلسه در IMemoryCache تحت یک توکن GUID تازه با انقضای لغزان ذخیره می‌شود — DocOptions.TimeOut دقیقه، پیش‌فرض ۶۰. هر درخواست صفحه ساعت را ریست می‌کند.
  3. ثبت امنیتی. با UnsafeMode = false (پیش‌فرض)، توکن به جلسه ASP.NET فراخوان متصل می‌شود: یک نشانگر secure-{token} در جلسه نوشته می‌شود، به‌طوری که فقط جلسه مرورگری که سند را باز کرده است می‌تواند صفحات آن را درخواست کند.
  4. توکن برگردانده می‌شود. این توکن اعتبارنامهٔ تک برای همهٔ موارد بعدی است.

سه نسخهٔ بارگذاری فقط در ورودی متفاوت هستند: مسیر فایل، مسیر فایل به‌همراه یک پیکربندی فرمت خاص (PdfConfig, WordConfig, …)، یا یک Stream به‌همراه یک FileInfo که پسوند آن تشخیص فرمت را هدایت می‌کند.

نحوه دریافت صفحات توسط ویجت

ویجت کلاینت با توکن در رشتهٔ پرس‌و‌جو، به میان‌افزار Doconut فراخوانی می‌کند. کاری که میان‌افزار انجام می‌دهد بستگی به درخواست دارد:

پرس‌و‌جوهدف
?token=…&page=Nتصویر صفحه رندر شده (PNG)
?token=…&page=N&thumb=1تصویر بندانگشتی
?token=…&zoom=…رندر صفحه با زوم
?token=…&search=termجستجوی تمام‌متن (محدود به مجوز)
?token=…&bookmarksطرح کلی/نشانک‌های سند
?token=…&copy / &showlinks / &fileFormatکپی متن، پیوندها، و اطلاعات فرمت
?token=…&metaمتادیتای فنی DICOM؛ برای یک جلسه DICOM در .NET 6 مقدار 501 برمی‌گرداند
?token=…&action=rotate/flip/closeاقدامات صفحه و بستن صریح
?token=…&AnnSave=… / &AnnLoadذخیره/بارگذاری حاشیه‌نویسی‌ها

هر یک از این مسیرها ابتدا اعتبارسنجی می‌شوند:

  • بدون توکن → میان‌افزار 404 برمی‌گرداند (یا بنر نسخه وقتی ShowDoconutInfo = true باشد).
  • توکن ناشناخته یا منقضی شده → تصویر خطا با متن Document session not found. Please re-open document.
  • میان‌افزار جلسه موجود نیست (با UnsafeMode = false) → HTTP 500 با متن Session middleware not configured. Call UseSession() before UseDoconut().
  • توکن توسط جلسه مرورگر متفاوتی باز شده است → تصویر خطا با متن You Are Not Authorized To View This Page.

بستن یک سند

csharp
viewer.CloseDocument(token);

CloseDocument جلسه را از کش حذف می‌کند (که موتور سند زیرین را آزاد می‌سازد و حافظهٔ آن را بلافاصله آزاد می‌کند)، نشانگر secure-{token} را پاک می‌کند و دسترسی را لغو می‌نماید. فراخوانی آن اختیاری است — انقضای لغزان همان پاک‌سازی را به‌صورت خودکار انجام می‌دهد — اما برای اسناد بزرگ این روش مودبانه برای آزادسازی حافظه در همان لحظه‌ای است که کاربر کار خود را تمام کرده است.

نکات کلیدی

  • یک سند باز = یک جلسه = یک توکن. توکن‌ها به‌ازای هر جلسه مرورگر هستند، نه URLهای سراسری.
  • توکن در یک بازهٔ لغزان منقضی می‌شود؛ یک Viewer که بیش از DocOptions.TimeOut بیکار بماند نیاز به بازگشایی مجدد دارد.
  • Viewer می‌تواند به‌صورت آزاد تزریق و به اشتراک گذاشته شود؛ جلسات تمام وضعیت را در خود دارند.

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