
無料 ASP.NET MVC ファイルマネージャー(組み込み PDF ビューア付き)
無料の ASP.NET MVC ファイルマネージャーを構築し、PDF を表示する方法
サーバーに保存されているファイルを一覧表示し、ユーザーがダウンロードまたは削除でき、PDF をサイトを離れずにブラウザ内で開くページが必要ですか?このガイドでは、シンプルな ASP.NET MVC、組み込みのセッションキャッシュ、そして Doconut のユニバーサルドキュメントビューアを使用して、まさにそれを実現する方法を示します。
1. 最小限の MVC アプリケーションを作成する
Visual Studio(無料の Community エディションを含む任意のエディション)で新しい MVC プロジェクトを作成します。
ファイルマネージャーのアクションをホストする FileController を追加します:
public class FileController : Controller
{
private readonly string _root = Path.Combine(Directory.GetCurrentDirectory(), "App_Data", "Docs");
public IActionResult Index()
{
var files = Directory.GetFiles(_root).Select(Path.GetFileName).ToList();
return View(files);
}
public IActionResult Download(string name)
{
var path = Path.Combine(_root, name);
if (!System.IO.File.Exists(path)) return NotFound();
var mime = "application/octet-stream";
return PhysicalFile(path, mime, name);
}
public IActionResult Delete(string name)
{
var path = Path.Combine(_root, name);
if (System.IO.File.Exists(path)) System.IO.File.Delete(path);
return RedirectToAction(nameof(Index));
}
public async Task<IActionResult> ViewPdf(string name)
{
var path = Path.Combine(_root, name);
if (!System.IO.File.Exists(path)) return NotFound();
// The viewer token is created here (see section 2)
var token = await _viewer.OpenDocumentAsync(
path,
new Doconut.PdfConfig { AllowSearch = true },
new DocOptions(),
CancellationToken.None);
ViewBag.Token = token;
ViewBag.BasePath = "doconut"; // matches the middleware branch
ViewBag.ResPath = "doconut-res/images";// embedded resources
return View();
}
private readonly Doconut.Viewer _viewer;
public FileController(Doconut.Viewer viewer) => _viewer = viewer;
}
コントローラは次の 3 つのことを行います:
- Index –
App_Data/Docsフォルダーを読み取り、ファイル名のリストをビューに渡します。 - Download / Delete – 組み込みの
PhysicalFileヘルパーを使用した標準的な MVC アクションです。 - ViewPdf – 選択された PDF を Doconut で開き、セキュリティトークンを取得して Razor ビューに渡します。
2. セッション状態と Doconut サービスを設定する
Doconut のビューアは、ドキュメントを識別するトークンを保護するために ASP.NET のセッション状態に依存しています。Program.cs(または .NET 6 プロジェクトの場合は Startup.cs)に必要なサービスを追加します:
var builder = WebApplication.CreateBuilder(args);
// MVC services
builder.Services.AddControllersWithViews();
// Session cache – required for token validation
builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession();
// Doconut registration – point to your license file
builder.Services.AddDoconut(options =>
{
options.LicensePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", "Doconut.Viewer.lic");
options.MiddlewarePath = "/doconut";
options.ResourcesPath = "/doconut-res";
options.UnsafeMode = false; // keep the default security
});
var app = builder.Build();
// Session must run before the viewer middleware
app.UseSession();
// The Doconut middleware must be mapped to the path configured above.
// See Doconut documentation for the exact mapping call (e.g., app.Map("/doconut", …)).
app.UseRouting();
app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute());
app.Run();
重要ポイント:
AddDistributedMemoryCacheはAddSessionが必要とするインメモリストアを提供します。UseSession()は Doconut ミドルウェアの前に配置 しなければなりません。そうしないと実行時エラー “Session middleware not configured.” が発生します。MiddlewarePathとResourcesPathは連携用の文字列です。実際のミドルウェアブランチは、設定したパスと一致している必要があります。
3. ファイルマネージャービューの作成
Views/File/Index.cshtml を作成します。このビューはファイルの一覧を表示し、ダウンロード、削除、PDF 表示のアクションを提供します。
@model List<string>
<h2>Document Library</h2>
<table>
<thead><tr><th>Name</th><th>Actions</th></tr></thead>
<tbody>
@foreach (var f in Model)
{
<tr>
<td>@f</td>
<td>
<a asp-action="Download" asp-route-name="@f">Download</a> |
<a asp-action="Delete" asp-route-name="@f">Delete</a> |
@if (Path.GetExtension(f).Equals(".pdf", StringComparison.OrdinalIgnoreCase))
{
<a asp-action="ViewPdf" asp-route-name="@f">View PDF</a>
}
</td>
</tr>
}
</tbody>
</table>
ユーザーが View PDF をクリックすると、ViewPdf アクションがトークンを生成し、ビューアウィジェットをホストする 2 番目のビューを返します。
4. Doconut ビューアのレンダリング
Views/File/ViewPdf.cshtml を作成します。このページはコンテナ要素だけが必要で、JavaScript ウィジェットは埋め込みリソースから読み込まれます。
@{
var token = ViewBag.Token as string;
var basePath = ViewBag.BasePath as string;
var resPath = ViewBag.ResPath as string;
}
<h2>PDF Preview</h2>
<div id="div_ctlDoc"></div>
<script src="@($"{basePath}/docViewer.js")"></script>
<link rel="stylesheet" href="@($"{basePath}/docViewer.css")" />
<script>
$('#div_ctlDoc').docViewer({
AccessToken: '@token',
BasePath: '@basePath',
ResPath: '@resPath',
FitType: 'width',
showThumbs: true,
autoLoad: true,
onError: function (msg) { console.error(msg); }
});
</script>
ウィジェットは提供された AccessToken を読み取り、/doconut/DocImage.axd エンドポイントに問い合わせ、各ページを画像としてストリーミングします。トークンは現在の ASP.NET セッションに紐付いているため、ユーザーは URL をコピーしても同じセッションクッキーがない別のブラウザからドキュメントを閲覧することはできません。
5. トークンの有効期限とセキュリティの取り扱い
Doconut のデフォルトのトークン有効期限は 60 分です(DocOptions.TimeOut で設定可能)。ビューアが “Document session not found” または “You Are Not Authorized To View This Page” を受け取った場合、セッションが期限切れになったか、別のブラウザコンテキストからのリクエストであることを意味します。
一般的な対策:
- ページをリフレッシュ – コントローラが新しいトークンを生成します。
- タイムアウトを延長 – ドキュメントを開く際にカスタム
DocOptionsを渡します。
var options = new DocOptions { TimeOut = TimeSpan.FromHours(2) };
var token = await _viewer.OpenDocumentAsync(
path,
new Doconut.PdfConfig { AllowSearch = true },
options,
CancellationToken.None);
- クロスオリジン設定 – セッションクッキーの
SameSite属性がフロントエンドのドメインと互換性があることを確認してください。デフォルトのLaxはほとんどの同一オリジンポータルで機能します。
6. マネージャーの拡張(オプション)
コアのファイルマネージャーはすでに機能していますが、以下の機能を追加したいかもしれません:
- アップロード –
IFormFileをポストし、_rootに保存するシンプルなフォーム。 - フォルダー ナビゲーション –
Indexアクションを変更して相対パスを受け取り、ディレクトリトラバーサル (Path.GetFullPath+StartsWith(_root)チェック) を防止します。 - 検索 – ビューに渡す前に
filesを名前でフィルタリングします。
これらすべての拡張は同じ MVC パターン内に収まり、同じセッション保護された Doconut ビューアの恩恵を受け続けます。
7. 達成したこと
- 無料 の ASP.NET MVC ファイルマネージャー – サードパーティの UI ライブラリ不要、ライセンス費用も不要。
- ブラウザ内 PDF レンダリング – Doconut のユニバーサルビューアを使用し、クライアント側に Office や Adobe のインストールが不要です。
- セキュアなトークンベースアクセス – ASP.NET セッション状態を利用し、任意の URL 共有を防止します。
- 単一コードベース – .NET 6 と .NET 8 の両方で動作し、Razor Pages や最小 API へ移行する場合も、登録呼び出し (
AddDoconut,UseSession) を変更するだけです。
アプリを IIS、Azure App Service、または Docker にデプロイしてください。同じ Program.cs 設定がどこでも機能します。Doconut は .NET 6 以上で動作し、ネイティブの Office コンポーネントは不要です。