关于异步请求后端文件下载的接口


? 我们知道,超链接如果直接链接到后端下载文件接口的路由,那么可以直接进行文件下载。那是因为浏览器会直接判断返回的数据类型(Response),但是,异步请求的话,返回的数据是交给异步请求来处理的,不是浏览器,所以不能够直接进行下载操作。

传统的Ajax请求

下载是浏览器的内置事件,而ajax请求将response交给了js来处理,而ajax只能处理接收的字符串进行处理,所以我们请求的是服务器返回的有中文乱码的二进制数据流

axios请求

axios请求可以接收二进制数据流,将responseType:'blob'添加至请求中即可,然后返回的二进制数据流进行处理,再触发浏览器的下载功能即可

演示

后端

@RequiresRoles("admin")
@GetMapping("/downloadGbsExcel")
public void downloadGbsExcel(HttpServletRequest request,HttpServletResponse response) {
    List gbsExcel = adminService.getGbsExcel();

    ExcelWriter writer = ExcelUtil.getWriter(true);//true为xlsx文件
    //设置写出excel别名
    writer.setHeaderAlias(ExcelGbsInfo.getheaderAlias());
    //将list中的数据,给ExcelWriter处理成Excel文件流
    writer.write(gbsExcel);

    //设置response请求头
    response.reset();//设置页面不缓存,清空buffer
    response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
    //        response.setContentType("multiple/form-data");
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
    response.setHeader("Content-Disposition", "attachment;filename=sx_gb_gs_table.xlsx");
    ServletOutputStream out ;
    try {
        out = response.getOutputStream();
        writer.flush(out);//将处理的Excel写入到输出流
        out.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    writer.close();
}

? 我这里是进行的excel下载,使用的hutool工具多excel数据进行封装,需要注意的是,如果是前后端分离项目,一定要加上:response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));这句,否则会出现:

Access to XMLHttpRequest at 'http://localhost:8081/admin/downloadGbsExcel' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

这样的错误提示,我这里下载的是excel所以请求类型是hutool提供的excel下载内容类型

前端

this.$axios({
    method: 'get',
    responseType:'blob',   //返回类型
    url: '/admin/downloadGbsExcel',
    headers: {
        "Authorization": localStorage.getItem("token")
    },
}).then(data=>{
    //通过返回的二进制流创建 Blob对象
    let blob = new Blob([data.data],
                        {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}
                       );
    let url = window.URL.createObjectURL(blob);
    //方式一:该url就是由返回的二进制流创建的文件下载地址,可以直接使用 window.location.href = url;下载
    //不过下载后需要手动修改文件名和后缀名
    
    //方式二:触发浏览器的内置下载功能
    let a = document.createElement('a')//创建一个a标签元素
    a.style.display = 'none'//设置为不显示
    a.href = url    //设置a标签的href属性
    a.setAttribute('download', '干部干事表.xlsx')//设置下载的文件名
    document.body.appendChild(a)//将a标签元素加入到页面中
    a.click()//触发点击
    document.body.removeChild(a) // 下载完成移除元素
    window.URL.revokeObjectURL(url) // 释放掉blob对象
})

通过触发该请求,完成了和a标签点击下载一样的效果!!!

相关