ビューアの仕組み
ドキュメント要求ライフサイクル
Doconut はドキュメントをページ分割された画像として ASP.NET Core ミドルウェアを通じて配信します。ライフサイクル(オープン、トークン、ページリクエスト、クローズ)を理解することで、エラーメッセージを含むほぼすべての挙動を説明できます。
3つの主要コンポーネント
Viewer— 注入するパブリックサービスです。ドキュメントを開き、セッショントークンを返します。- ドキュメントセッション — ロードされたドキュメントを保持するサーバー側オブジェクトで、
IMemoryCacheのトークンをキーにしています。 - Doconut ミドルウェア は
UseDoconut()によって追加され、ブラウザウィジェットが行うすべてのリクエスト(pages、thumbnails、search、annotations、…)に応答します。常にトークンで認証されます。
Viewer はステートレス — 設計上
Viewer はシールドされており、リクエストごとのドキュメント状態を保持せず、意図的に 実装 しません IDisposable。セッションはセッションマネージャー内で独立して存在し、キャッシュの期限切れまたは明示的な CloseDocument(token) によってクリーンアップされます。
もはや自分で構築する必要はありません。AddDoconut() はそれをトランジェントサービスとして登録します。必要な場所へ注入してください:
app.MapPost("/api/open", async (string fileName, Viewer viewer) =>
{
var token = await viewer.OpenDocumentAsync($"files/{fileName}");
return Results.Content(token, "text/plain");
});MVC アプリケーションではコンストラクタパラメータとして取得し、Razor ビューでは @inject Doconut.Viewer Viewer を使用します。Viewer インスタンスのアプリケーション所有キャッシュは不要になり、キャッシュすべきものが何もないため正しくありません。
OpenDocumentAsync の内部で何が起こるか
- ライセンスゲート。 拒否された、またはバージョン期限切れのライセンス(ブラックリスト登録、改ざん、またはライセンスの更新ウィンドウ外のビルド)は、即座に
LicenseExceptionをスローし、拒否理由をメッセージとして提供します — 無効な(欠如しているのとは異なる)ライセンスの場合、オープンは決して黙って劣化しません。カレンダー期限切れの一時またはサブスクリプションライセンスは例外で、スローせずに透かしに劣化します。 - セッション作成。 ビューワーファクトリはファイル拡張子に適したフォーマットビューワーを選択し、ドキュメントをロードします(Rendering Pipeline を参照)。セッションは新しい GUID トークンで
IMemoryCacheに保存され、スライディング有効期限 —DocOptions.TimeOut分(デフォルト 60)を持ちます。各ページリクエストでタイマーがリセットされます。 - セキュリティ登録。 デフォルトの
UnsafeMode = falseを使用すると、トークンは呼び出し元の ASP.NET セッションに結び付けられます:secure-{token}マーカーがセッションに書き込まれ、ドキュメントを開いたブラウザセッションだけがページをリクエストできるようになります。 - トークンが返されます。 以降のすべての操作の唯一の認証情報です。
別個のウォームアップステップはありません。以前のライブラリはその目的で InitCache() を提供していましたが、現在は存在せず、代替もありません。
3つのオーバーロードは入力のみが異なります:ファイルパス、ファイルパスにフォーマット別設定(PdfConfig、WordConfig、…)を加えたもの、または拡張子でフォーマット検出を行う Stream と FileInfo の組み合わせです。
ウィジェットがページを取得する方法
クライアントウィジェットはクエリ文字列にトークンを付けて Doconut ミドルウェアを呼び出します。ミドルウェアの動作はリクエストに依存します:
| クエリ | 目的 |
|---|---|
?token=…&page=N | レンダリングされたページ画像(PNG) |
?token=…&page=N&thumb=1 | サムネイル |
?token=…&zoom=… | 拡大ページレンダリング |
?token=…&search=term | 全文検索(ライセンス制御) |
?token=…&bookmarks | ドキュメントアウトライン/ブックマーク |
?token=…© / &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がある場合)→Session middleware not configured. Call UseSession() before UseDoconut().を伴う HTTP 500。 - 別のブラウザセッションでトークンが開かれた →
You Are Not Authorized To View This Page.を含むエラー画像。
ミドルウェアのマウント場所
UseDoconut() はトークンを含むリクエストに応答し、マウント場所に関係なく動作します。リファレンスアプリケーションは歴史的な DocImage.axd リクエスト形状を MapWhen ブランチ上に保持しているため、既存クライアントは常に同じ URL を呼び出し続けます。選択するものにかかわらず、クライアントの BasePath はそれと一致する必要があります — ViewerConfig を参照してください。
ページを開くノードではなく共有ストレージから提供する場合は、全く別の構成になります;Distributed Deployments を参照してください。
ドキュメントのクローズ
viewer.CloseDocument(token);CloseDocument はキャッシュからセッションを削除し(基盤となるドキュメントエンジンを破棄し、メモリを即座に解放)、secure-{token} マーカーを削除し、アクセス権を取り消します。呼び出しは任意です — スライディング有効期限が同様のクリーンアップを自動で行います — が、大きなドキュメントの場合、ユーザーが終了した瞬間にメモリを解放する礼儀正しい方法です。
これは注入された Viewer 上で呼び出されます。以前のパターン — トークンを閉じるだけの短命な Viewer を using ブロック内で構築する — は同等のものがなく、必要ありません。
まとめ
- 1つのオープンドキュメント = 1つのセッション = 1つのトークン。トークンはブラウザセッションごとに付与され、グローバルURLではありません。
- トークンはスライディングウィンドウで期限切れになります;
DocOptions.TimeOutを超えてアイドル状態のビューアは再オープンが必要です。 Viewerは注入して自由に共有できます;セッションがすべての状態を保持します。
このページは役に立ちましたか?