Бесплатный менеджер файлов ASP.NET MVC с встроенным просмотрщиком PDF
← Back to Blog••5 min read

Бесплатный менеджер файлов ASP.NET MVC с встроенным просмотрщиком PDF

Создайте бесплатный менеджер файлов ASP.NET MVC, отображающий PDF

Вам нужна страница, которая выводит список файлов, хранящихся на сервере, позволяет пользователю скачивать или удалять их и открывать любой PDF в браузере без перехода с сайта. Следующее руководство покажет, как сделать именно это с помощью обычного ASP.NET MVC, встроенного кэша сессий и универсального просмотрщика документов Doconut.


1. Создайте минимальное MVC‑приложение

Создайте новый MVC‑проект в Visual Studio (любая редакция, включая бесплатную Community).

Добавьте 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;
}

Контроллер выполняет три действия:

  1. Index – читает папку App_Data/Docs и передаёт имена файлов в представление.
  2. Download / Delete – стандартные MVC‑действия, использующие встроенный помощник PhysicalFile.
  3. ViewPdf – открывает выбранный PDF с помощью Doconut, получает токен безопасности и передаёт его в Razor‑представление.

2. Настройте состояние сессии и сервисы Doconut

Просмотрщик Doconut опирается на состояние сессии ASP.NET для защиты токена, идентифицирующего документ. Добавьте необходимые сервисы в Program.cs (или Startup.cs для проектов .NET 6):

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 предоставляет in‑memory хранилище, необходимое AddSession.
  • UseSession() должен вызываться до middleware Doconut; иначе вы получите ошибку выполнения “Session middleware not configured.”
  • MiddlewarePath и ResourcesPath — согласующие строки; фактическая ветка middleware должна соответствовать указанному пути.

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 создаёт токен и возвращает второе представление, в котором размещён виджет просмотрщика.


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 и открыть документ в другом браузере без того же cookie‑сеанса.


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);
  • Настройки кросс‑origin — убедитесь, что атрибут SameSite у cookie‑сессии совместим с доменом вашего фронтенда. Значение 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.

#ASP.NET MVC#File Manager#PDF Viewer#.NET#Doconut#Менеджер файлов#Просмотрщик PDF