Blazor 服务器:强制文件下载

Blazor Server: Force file download

在我的网站 MySpector.com 开发的上下文中,使用 Blazor Server 开发, 我想让用户可以下载存储在机器磁盘上的文件。 为此,我想创建一个 Blazor 组件/页面(我不知道是什么),它将:

我无法理解如何使用 Blazor 对 http 响应 headers 和内容进行编程。 我在 Blazor download on microsoft 上看到了一个潜在的解决方案,但我不喜欢在 BLAZOR 解决方案中创建 RAZOR 页面的想法,因为这引入了一个以不同于另一个(2 个文件:.cshtml + .cshtml.cs,而不是 1 个 .razor 文件)

在文件层次结构中查看下面 Downloader.cshtml,它看起来与其他页面不同。

我也知道 blazor 服务器的 'different layers',其中页面只是更大 html 上下文的一部分,所以我看到了问题,但我想找到一个简单的方法仅通过 .razor 单个文件覆盖 http GET...如果可能的话。

此致。

您可以使用 Asp 网络核心控制器通过 headers 控制 http 响应。这与 Blazor 服务器技术兼容。 为此,您可以访问以下 2 个链接:

我用下载器控制器添加了一个控制器目录:

我用这个差异修补了启动代码:

然后我添加下载器控制器的代码:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Net.Mime;
using System.Web;
using NLog;
using MySpector.Core;
using MySpector.Objects;

//https://chanmingman.wordpress.com/2020/07/12/add-web-api-controller-to-blazor-project-asp-net/
//https://whosebug.com/questions/5826649/returning-a-file-to-view-download-in-asp-net-mvc


namespace FrontEnd.Pages
{
    [Route("api/[controller]")]
    [ApiController]
    public class DownloadController : Controller
    {
        private static Logger _log = LogManager.GetCurrentClassLogger();
        private ResultStorage _resultStorage;
    // GET /api/Download/3
    [HttpGet("{resultDbId:int}")] 
    public ActionResult Get(int resultDbId)
    {
        bool isConnected = ServiceLocator.Instance.Repo.Connect();
        if (!isConnected)
        {
            _log.Error("Cannot connect");
            _log.Error("Returning Http 404");
            return NotFound();
        }
        else
        {
            _log.Debug("Connected to db");
            _log.Debug("Input: ResultDbId=" + resultDbId);
            _resultStorage = ServiceLocator.Instance.Repo.GetSingleResult(resultDbId);
        }
        if(_resultStorage==null)
        {
            _log.Error("Returning Http 404");
            return NotFound();
        }
        string filename = _resultStorage.File.FilePath;
        var cd = new ContentDisposition
        {
            FileName = filename,
            Inline = true,
        };
        Response.Headers.Add("Content-Disposition", cd.ToString());
        byte[] filedata = System.IO.File.ReadAllBytes(filename);
        string contentType = "application/octet-stream";
        return File(filedata, contentType);
    }
}
}

然后您可以调用此模块:

        string downloadUri = "api/Download/" + @_report.Result.DbId;
        <NavLink href="@downloadUri">Download raw file</NavLink><br />