Reputation: 899
In the context of the development of my website MySpector.com developed with Blazor Server, I want to give the user the possibility to download files which are stored on the disk of the machine. To do this I want to create a Blazor Component / Page ( I do not know what) which will:
I am having problem to understand how I can program the http response headers and content with Blazor. I have seen a potential solution on Blazor download on microsoft but I do not like the idea to create a RAZOR page inside a BLAZOR solution, as this introduce a component organized in a different way than the other ( 2 files: .cshtml + .cshtml.cs, instead of 1 .razor file)
see below Downloader.cshtml in the file hierarchy which looks like different than the other pages.
I am also aware of the 'different layers' of blazor server where a page is only a subpart of a bigger html context so I see the problem, but I woudl like to find a easy way only to override http GET via a .razor single file... if this is possible.
Regards.
Upvotes: 1
Views: 1251
Reputation: 899
You can get control of the http response with headers by using a Asp net core Controller. This is compatible with Blazor server technology. To do so, you can folow up the 2 links below:
I added a controller directory with the downloader controller:
I patch the code of startup with this diff:
Then I add the code for the downloader controller:
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://stackoverflow.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);
}
}
}
You can then call this module with:
string downloadUri = "api/Download/" + @_report.Result.DbId;
<NavLink href="@downloadUri">Download raw file</NavLink><br />
Upvotes: 0