vue中使用asiox下载后端响应在response中的文件流

本文介绍了如何在Vue应用中使用axios封装的doGetBlob方法实现文件下载,包括前端模板的使用、后端SpringBoot提供使用easyExcel生成的Excel文件下载接口,以及确保Content-Disposition头信息正确设置以支持跨域请求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、vue代码

<template>
    <el-button slot="append" @click="Down()">测试下载</el-button>
</template>
<script>
import {doGetBlob} from "@/api/httpRequest";

export default {
    name: "downView",
    data() {
    },
    created() {
    },
    methods: {
        Down() {
            doGetBlob("/down/eFile?id=1").then(response => {
                const fileName = decodeURI(response.headers['content-disposition'].split('=')[1]);
                const url = window.URL.createObjectURL(new Blob([response.data]));
                const link = document.createElement('a');
                link.href = url;
                link.setAttribute('download', fileName);
                document.body.appendChild(link);
                link.click();
            }).catch(err => {
                    console.log("异常" + err);
                    console.log(err);
                })
        }
    }
}
</script>
<style scoped>
</style>

2、doGetBlob代码

import axios from "axios";
axios.defaults.baseURL = "http://127.0.0.1:8008";
axios.defaults.timeout = 30000


/**
 * 封装get请求
 * @param url
 */
function doGet(url, params) {
    return axios({
        url: url,
        method: 'get',
        params: params,
        withCredentials: true
    });
}

function doGetBlob(url){
    return axios({
        method:'get',
        url: url,
        responseType:'blob',
        withCredentials: true
    })
}

export {doGetBlob, doGet};

3、后端下载接口(使用easyExcel创建的excel文件)

@RestController
@RequestMapping("/down")
public class DownController {

    @RequestMapping("eFile")
    public void downEFile(int id, HttpServletResponse response) {
        try {
            String fileName = "";
            if (id>0){
                fileName = "文件1.xlsx";
            }else {
                fileName = "文件2.xlsx";
            }
            List<Book> list = new ArrayList<>();
            Book book = new Book();
            book.setBookName("语文");
            BigDecimal abp = new BigDecimal(10.0);
            book.setBookPrice(abp);
            list.add(book);
            fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
            OutputStream out = response.getOutputStream();
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName);
            ExcelWriter excelWriter = EasyExcelFactory.write(out).build();
            EasyExcel.write(response.getOutputStream(), Book.class)
                    .sheet("sheet")
                    .doWrite(list);
            excelWriter.finish();
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4、其中的Book类

@TableName("book")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book implements Serializable {
    private static final long serialVersionUID = 1L;
    @TableId
    private Integer bookId;
    private String bookName;
    private BigDecimal bookPrice;
    private Date bookCreateTime;
    private Date createTime;
    private Date updateTime;
    private String updateUserId;
}

5、一定要注意设置响应头允许携带Content-Disposition(否则axios请求中获取不到文件名称)

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        //设置允许Cookie
        response.setHeader("Access-Control-Allow-Credentials", "true");
        //跨域请求,*代表允许全部类型
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        //用来指定本次预检请求的有效期,单位为秒,在此期间不用发出另一条预检请求
        response.setHeader("Access-Control-Max-Age", "3600");
        //请求包含的字段内容,如有多个可用哪个逗号分隔如下
        response.setHeader("Access-Control-Allow-Headers", "uid,Authorization,content-type,x-requested-with,Authorization, x-ui-request,lang");
        //访问控制允许凭据,true为允许
        response.setHeader("Access-Control-Allow-Credentials", "true");
        // 浏览器是会先发一次options请求,如果请求通过,则继续发送正式的post请求,配置options的请求返回
        if (request.getMethod().equals("OPTIONS")) {
            response.setStatus(200);
            response.getWriter().write("OPTIONS returns OK");
            return;
        }
        chain.doFilter(request, response);
    }
    @Override
    public void destroy() {
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}

6、至此完成

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值