这篇文章上次修改于 290 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

服务端

服务端代码实现很简单,如下所示:

[HttpGet]
public IActionResult Download()
{
    var fileStream = System.IO.File.OpenRead("D:/files/students.xlxs");
    return File(fileStream, "application/octet-stream", HttpUtility.UrlEncode("学生名单.xlsx"));
}

这里需要注意的是 File() 方法的第三个参数 fileDownloadName,若该参数含有中文需要进行 Url 编码,否则客户端浏览器会乱码。

服务端还有一个需要注意的地方,在 Startup.cs 文件中,需要在 ConfigureServices 方法中做如下设置,否则客户端浏览器不能读取响应头中的 Content-Disposition,无法获取服务端设置的文件下载名。

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddDefaultPolicy(
            builder =>
            {
                builder.WithExposedHeaders("Content-Disposition"); // 将响应头中的 Content-Disposition 暴露给客户端访问
            }
        );
    });
}

至此,服务端的工作全部完成。

客户端浏览器

客户端浏览器请求并下载服务端文件脚本如下:

this.$axios
        .get('/File/Download', {
          responseType: "blob",
        })
        .then((resp) => {
          const fileName = decodeURIComponent(
            resp.headers["content-disposition"].split(";")[1].split("=")[1]
          );
          const url = window.URL.createObjectURL(new Blob([resp.data]));
          const link = document.createElement("a");
          link.href = url;
          link.setAttribute("download", fileName);
          document.body.appendChild(link);
          link.click();
          document.body.removeChild(link);

          this.$message.success("下载成功");
        })
        .catch((err) => {
            this.$message.error(err);
        });

有几个需要注意的点:

  1. axios 请求参数中的 responseType 需要设置成 blob
  2. 服务端提供的下载文件名通过解析响应头 content-disposition 中的 filename 获得,同时还要注意使用 decodeURIComponent 解码 url
  3. 创建文件下载超链接,并模拟点击实现文件自动下载