Blazor 服务器:强制文件下载
Blazor Server: Force file download
在我的网站 MySpector.com 开发的上下文中,使用 Blazor Server 开发,
我想让用户可以下载存储在机器磁盘上的文件。
为此,我想创建一个 Blazor 组件/页面(我不知道是什么),它将:
- 输入一个数据库ID,
- 获取数据库以在磁盘中定位文件
- 将要下载的数据动态传输到网络浏览器
我无法理解如何使用 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 />
在我的网站 MySpector.com 开发的上下文中,使用 Blazor Server 开发, 我想让用户可以下载存储在机器磁盘上的文件。 为此,我想创建一个 Blazor 组件/页面(我不知道是什么),它将:
- 输入一个数据库ID,
- 获取数据库以在磁盘中定位文件
- 将要下载的数据动态传输到网络浏览器
我无法理解如何使用 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 />