نحوه کار Viewer

دوره‌حیات درخواست سند

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

سه بخش متحرک

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

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

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

دیگر نیازی به ساختن آن ندارید. AddDoconut() آن را به‌عنوان سرویس موقت ثبت می‌کند؛ هر جایی که نیاز دارید تزریق کنید:

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

در یک برنامه MVC، آن را به‌عنوان پارامتر سازنده بگیرید؛ در یک Razor view، از @inject Doconut.Viewer Viewer استفاده کنید. کش‌های متعلق به برنامه برای نمونه‌های Viewer دیگر نیازی ندارند — و دیگر صحیح نیستند، زیرا هیچ چیزی برای کش کردن ندارند.

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

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

مرحله‌ی گرم‌کردن جداگانه‌ای وجود ندارد. کتابخانه‌ی قبلی InitCache() را برای این منظور ارائه می‌داد؛ دیگر وجود ندارد و هیچ‌چیزی جایگزین آن نشده است.

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

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

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

Queryهدف
?token=…&page=Nتصویر صفحه رندر شده (PNG)
?token=…&page=N&thumb=1تصویر کوچک
?token=…&zoom=…رندر صفحه با زوم
?token=…&search=termجستجوی تمام متن (محدود به مجوز)
?token=…&bookmarksطرح سند/بوکمارک‌ها
?token=…&copy / &showlinks / &fileFormatکپی متن، پیوندها، و اطلاعات فرمت
?token=…&metaمتادیتای فنی DICOM؛ برای یک جلسه DICOM در این بسته 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.

محل نصب میدل‌ویر

UseDoconut() درخواست‌هایی که توکن دارند را پاسخ می‌دهد، هر جایی که آن را نصب کنید. برنامهٔ مرجع شکل تاریخی درخواست DocImage.axd را در یک شاخهٔ MapWhen حفظ می‌کند، بنابراین یک کلاینت موجود همچنان همان URL را صدا می‌زند. هر چه انتخاب کنید، BasePath کلاینت باید با آن مطابقت داشته باشد — به ViewerConfig مراجعه کنید.

سرو کردن صفحات از ذخیره‌سازی مشترک به‌جای گرهٔ بازکننده یک ترتیب کاملاً متفاوت است؛ به استقرارهای توزیع‌شده مراجعه کنید.

بستن یک سند

csharp
viewer.CloseDocument(token);

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

این متد بر روی Viewer تزریق‌شده فراخوانی می‌شود. الگوی قبلی — ساختن یک Viewer کوتاه‌عمر در یک بلوک using صرفاً برای بستن توکن — معادلی ندارد و نیازی به آن نیست.

نکات کلیدی

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

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