Trình quản lý tệp ASP.NET MVC miễn phí với Trình xem PDF tích hợp
← Back to Blog••6 min read

Trình quản lý tệp ASP.NET MVC miễn phí với Trình xem PDF tích hợp

Xây dựng Trình quản lý tệp ASP.NET MVC miễn phí hiển thị PDF

Bạn muốn một trang liệt kê các tệp được lưu trên máy chủ, cho phép người dùng tải xuống hoặc xóa chúng, và mở bất kỳ tệp PDF nào trong trình duyệt mà không rời khỏi trang web. Hướng dẫn dưới đây sẽ chỉ cho bạn cách thực hiện điều đó bằng ASP.NET MVC thuần, bộ nhớ đệm phiên tích hợp, và trình xem tài liệu đa năng của Doconut.


1. Tạo một Ứng dụng MVC tối thiểu

Tạo một dự án MVC mới trong Visual Studio (bất kỳ phiên bản nào, bao gồm cả phiên bản Community miễn phí).

Thêm một FileController sẽ chứa các hành động quản lý tệp:

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();

        // Token trình xem được tạo ở đây (xem mục 2)
        var token = await _viewer.OpenDocumentAsync(
            path,
            new Doconut.PdfConfig { AllowSearch = true },
            new DocOptions(),
            CancellationToken.None);

        ViewBag.Token = token;
        ViewBag.BasePath = "doconut";          // khớp với nhánh middleware
        ViewBag.ResPath = "doconut-res/images";// tài nguyên nhúng
        return View();
    }

    private readonly Doconut.Viewer _viewer;
    public FileController(Doconut.Viewer viewer) => _viewer = viewer;
}

Controller thực hiện ba việc:

  1. Index – đọc thư mục App_Data/Docs và truyền tên các tệp tới một view.
  2. Download / Delete – các hành động MVC tiêu chuẩn sử dụng trợ giúp PhysicalFile tích hợp.
  3. ViewPdf – mở PDF đã chọn bằng Doconut, nhận token bảo mật và truyền nó tới một Razor view.

2. Kết nối Trạng thái Phiên và Dịch vụ Doconut

Trình xem của Doconut dựa vào trạng thái phiên ASP.NET để bảo vệ token xác định tài liệu. Thêm các dịch vụ cần thiết trong Program.cs (hoặc Startup.cs cho các dự án .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();

Các điểm quan trọng:

  • AddDistributedMemoryCache cung cấp kho lưu trữ trong bộ nhớ mà AddSession cần.
  • UseSession() phải xuất hiện trước middleware của Doconut; nếu không bạn sẽ gặp lỗi runtime “Session middleware not configured.”
  • MiddlewarePath và ResourcesPath là các chuỗi phối hợp – nhánh middleware thực tế phải khớp với đường dẫn bạn cấu hình.

3. Tạo Giao Diện Quản Lý Tập Tin

Tạo Views/File/Index.cshtml. Nó liệt kê các tệp và cung cấp các hành động để tải xuống, xóa và xem 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>

Khi người dùng nhấp View PDF, hành động ViewPdf sẽ tạo một token và trả về một view thứ hai chứa widget xem tài liệu.


4. Hiển Thị Trình Xem Doconut

Tạo Views/File/ViewPdf.cshtml. Trang chỉ cần một phần tử chứa; widget JavaScript được tải từ các tài nguyên nhúng.

@{
    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>

Widget đọc AccessToken bạn cung cấp, liên hệ với endpoint /doconut/DocImage.axd, và truyền từng trang dưới dạng hình ảnh. Vì token được liên kết với phiên ASP.NET hiện tại, người dùng không thể sao chép URL và xem tài liệu từ trình duyệt khác nếu không có cùng cookie phiên.


5. Xử Lý Hết Hạn Token và Bảo Mật

Thời gian hết hạn token mặc định của Doconut là 60 phút (có thể cấu hình qua DocOptions.TimeOut). Nếu trình xem nhận được “Document session not found” hoặc “You Are Not Authorized To View This Page”, phiên đã hết hạn hoặc yêu cầu đến từ ngữ cảnh trình duyệt khác.

Các biện pháp thường gặp:

  • Làm mới trang – bộ điều khiển sẽ tạo một token mới.
  • Tăng thời gian chờ – truyền một DocOptions tùy chỉnh khi mở tài liệu:
var options = new DocOptions { TimeOut = TimeSpan.FromHours(2) };
var token = await _viewer.OpenDocumentAsync(
    path,
    new Doconut.PdfConfig { AllowSearch = true },
    options,
    CancellationToken.None);
  • Cấu hình cross‑origin – đảm bảo thuộc tính SameSite trên cookie phiên tương thích với miền front‑end của bạn. Giá trị mặc định Lax hoạt động tốt cho hầu hết các cổng cùng nguồn.

6. Mở Rộng Trình Quản Lý (Tùy Chọn)

Trình quản lý tệp cốt lõi đã hoạt động, nhưng bạn có thể muốn thêm:

  • Upload – một biểu mẫu đơn giản gửi một IFormFile và lưu nó vào _root.
  • Duyệt thư mục – sửa đổi hành động Index để nhận một đường dẫn tương đối và bảo vệ nó khỏi tấn công traversal (Path.GetFullPath + kiểm tra StartsWith(_root)).
  • Tìm kiếm – lọc files theo tên trước khi truyền vào view.

Tất cả các mở rộng này vẫn nằm trong cùng mẫu MVC và tiếp tục hưởng lợi từ Doconut viewer được bảo vệ bằng session.


7. Những Điều Bạn Đã Đạt Được

  • Một miễn phí ASP.NET MVC file manager – không có thư viện UI bên thứ ba, không phí bản quyền.
  • Kết xuất PDF trong trình duyệt qua Doconut’s universal viewer, tránh việc phải cài đặt Office hoặc Adobe trên máy khách.
  • Truy cập dựa trên token bảo mật tận dụng trạng thái session của ASP.NET, ngăn chặn việc chia sẻ URL một cách tùy tiện.
  • Một cơ sở mã duy nhất hoạt động trên .NET 6 và .NET 8 và có thể chuyển sang Razor Pages hoặc minimal APIs chỉ bằng cách thay đổi các lời gọi đăng ký (AddDoconut, UseSession).

Triển khai ứng dụng lên IIS, Azure App Service, hoặc Docker – cấu hình Program.cs giống nhau hoạt động ở mọi nơi vì Doconut chạy trên .NET 6+ và không yêu cầu bất kỳ thành phần Office gốc nào.

#ASP.NET MVC#File Manager#PDF Viewer#.NET#Doconut#Trình quản lý tệp#Trình xem PDF