Blazor 中如何下载文件到浏览器

Blazor 中如何下载文件到浏览器

Blazor 中如何下载文件浏览器

独立观察员 2021年3月28日

一、前言

最近想给之前文章《下载中转加速器 VPSDownloader.NET(.NET Core 程序部署到 Linux 系统)》中提到的 VPS 文件中转下载服务添加一个前端页面,其实之前也想使用热门的前端框架 Vue 来做,也做了点工作了,但是毕竟不是前端开发,上手起来还是比较慢的,而且引入了 NodeJS 等技术栈,和后端的 ASP.NET Core WebApi 也不共存于一个项目,开发和维护起来不太方便。后来了解到了发展如火如荼的 Blazor 框架,这个是微软开发的 .NET 领域的前端框架,在某种程度上和以前的 WebForm 有点类似,不过以前那个是微软自己搞的,大家都不待见它,现在这个是符合 Web 领域新标准 WebAssembly,而且 UI 方面也可以使用现有的成熟库。总之,使用 Blazor,可以使用 C# 代码来代替(当然也是兼容的)JavaScript 代码,使 .NET 开发人员能有极致的全栈开发体验,颠覆以往那种“师夷长技以制夷”的前端开发方式,所以决定学习使用一下。另外,本文的 Blazor 项目使用 Blazor Server 模式,而不是 Blazor WebAssembly 模式。

 

先来前情回顾一下,关键就是 WebApi 项目提供了一个 Download 控制器的 Get 方法:

/// <summary>
/// 通过HttpClient获取另外站点的文件流,再输出
/// </summary>
[HttpGet]
public async Task<IActionResult> Get(string url)
{
    if (string.IsNullOrWhiteSpace(url))
    {
        _logger.LogTrace("下载地址为空!");
        return Content("请在链接后跟上下载地址后再次访问");
    }

    try
    {
        //解决 CentOS7 Https 下载地址出错的问题;
        var httpClientHandler = new HttpClientHandler
        {
            ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) => true
        };

        using HttpClient client = new HttpClient(httpClientHandler);
        var stream = await client.GetStreamAsync(url);
        return File(
            stream,
            "application/octet-stream", //二进制流
            Path.GetFileName(url));
    }
    catch (Exception ex)
    {
        return Content($"出错了:{ex}");
    }
}

 

之前是使用 Swagger 测试的,实际上用 Postman 也可以测试:

Blazor 中如何下载文件到浏览器插图

 

二、方法一(导航跳转)

那么我们在 Blazor 中如何调用呢?先来看个简单的:

Blazor 中如何下载文件到浏览器插图1

 

可以看到直接使用 Navigation.NavigateTo 跳转到相关 WebApi 地址即可。由于该接口返回二进制流,浏览器就能直接识别进行下载了(动图):

Blazor 中如何下载文件到浏览器插图2

 

这种方法只是起个跳转的作用,实际下载动作还是在 WebApi  那边进行,缺点是下载结果不可知,优点是下载过程可见。

这个实际上不是本文讨论的重点,本文讨论的是,使用代替了 JS 代码的 C# 代码来下载文件到浏览器。

 

三、方法二(下载后传出)

那么如何实现呢?这个要分两步走,第一步是使用代码调用 API 进行下载文件,第二步是使用某种方法把文件通过浏览器传出给用户。

 

(一) 使用 RestSharp 下载

先来看看第一步,这里我们通过 Postman 得知可以使用 RestSharp 进行调用:

Blazor 中如何下载文件到浏览器插图3

 

我们通过 NuGet 安装 RestSharp 后,代码可以这样写:

var client = new RestClient($"http://frps.dlgcy.com:5000/Download?url={Url}");
var request = new RestRequest(Method.GET);
var response = await client.ExecuteAsync(request);

if (response.IsSuccessful)
{
    Tips = "下载成功!";

    var content = response.Content;
    var contentBytes = response.RawBytes;

    await BlazorDownloadFileService.DownloadFile(Path.GetFileName(Url), contentBytes, "application/octet-stream");
}
else
{
    Tips = "下载失败!";
}

 

(二) 使用 BlazorDownloadFile 传出

再来看看第二步,把下载的文件传出给用户,方法就是使用 BlazorDownloadFile 开源方案。

GitHub 地址:https://github.com/arivera12/BlazorDownloadFile

Blazor download files to the browser from c# without any JavaScript library or dependency.

BlazorDownloadFile is the solution to saving files on the client-side, and is perfect for web apps that generates files on the client.

However if the file is coming from the server we recommend you to first try to use Content-Disposition attachment response header as it has more cross-browser compatibility.

 

翻译:

在 Blazor 中通过 C#(不使用任何 JS 库和依赖)下载文件到浏览器。

BlazorDownloadFile 是在客户端保存文件的解决方案,它对于在客户端生成文件的应用来说是完美的。

然而如果文件是来自服务端,我们建议您优先使用 Content-Disposition 附件响应头,因为它有更好的跨浏览器兼容性。

 

1、安装(NuGet)

Install-Package BlazorDownloadFile -Version 2.1.6

 

2、添加服务

在 Startup 的 ConfigureServices() 中添加:

services.AddBlazorDownloadFile();

 

3、在 Blazor 的 Razor 页面中使用(2021.04.03更新)

//在页首添加引用:
@using BlazorDownloadFile
//可以直接这样注入;
@inject IBlazorDownloadFileService BlazorDownloadFileService

//在 code 中注入(可换为使用上面的注入方式):
//[Inject] IBlazorDownloadFileService BlazorDownloadFileService { get; set; }

//使用(这里是先获得了文件的字节数组再调用本方法)
await BlazorDownloadFileService.DownloadFile(Path.GetFileName(Url), contentBytes, "application/octet-stream");

 

图示:

Blazor 中如何下载文件到浏览器插图4

 
这样就可以根据下载是否成功来分别处理,成功时传出文件给用户,缺点是下载过程用户不可知,还需优化,效果如下(动图):
Blazor 中如何下载文件到浏览器插图5
 
最后给出源码地址:

https://gitee.com/dlgcy/VPSDownloader.NET/tree/Blog20210328

 

全文完,感谢阅读。

 

发表评论