• Springboot 文件下载代码


    一。JSP 式样的

    public HttpServletResponse download(String path, HttpServletResponse response) {
            try {
                // path是指欲下载的文件的路径。
                File file = new File(path);
                // 取得文件名。
                String filename = file.getName();
                // 取得文件的后缀名。
                String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();
    
                // 以流的形式下载文件。
                InputStream fis = new BufferedInputStream(new FileInputStream(path));
                byte[] buffer = new byte[fis.available()];
                fis.read(buffer);
                fis.close();
                // 清空response
                response.reset();
                // 设置response的Header
                response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
                response.addHeader("Content-Length", "" + file.length());
                OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
                response.setContentType("application/octet-stream");
                toClient.write(buffer);
                toClient.flush();
                toClient.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            return response;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    二。前后端下载代码的逻辑:

    如果后台返回的是文件地址,那么前端直接通过 window.location.href 加文件地址,就可以下载文件;

    但是如果后台返回的是文件流,那么前端就需要做一些处理;

    其实前端处理的核心:就是将文件流转为文件,然后再模拟点击,实现前者的效果。


    前端:

    const blob = new Blob([res], {
    // 设置返回的文件类型
    // type: 'application/pdf;charset=UTF-8' 表示下载文档为pdf,如果是word则设置为msword,excel为excel
    type: type
    })
    // 这里就是创建一个a标签,等下用来模拟点击事件
    const a = document.createElement('a')
    // 兼容webkix浏览器,处理webkit浏览器中href自动添加blob前缀,默认在浏览器打开而不是下载
    const URL = window.URL || window.webkitURL
    // 根据解析后的blob对象创建URL 对象
    const herf = URL.createObjectURL(blob)
    // 下载链接
    a.href = herf
    // 下载文件名,如果后端没有返回,可以自己写a.download = '文件.pdf'
    a.download = filename
    document.body.appendChild(a)
    // 点击a标签,进行下载
    a.click()
    // 收尾工作,在内存中移除URL 对象
    document.body.removeChild(a)
    window.URL.revokeObjectURL(herf)
    }</pre>
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    这里用简单的问题:遇到了四个问题:
    1.主机被迫连接中断,捕捉异常处理
    2.vue 超时处理
    3.reset 问题。
    4.getOutputStream() has already been called for this response的解决方法,值为空,modelAndView,@ResponseBody都不行

    最后的解决方法:

    @GetMapping("/t1")
        public void down1(HttpServletResponse response) throws Exception {
            response.reset();
            response.setContentType("application/octet-stream;charset=utf-8");
            response.setHeader(
                    "Content-disposition",
                    "attachment; filename=test.png");
            try(
                    BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\desktop\\1.png"));
                    // 输出流
                    BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
            ){
                byte[] buff = new byte[1024];
                int len = 0;
                while ((len = bis.read(buff)) > 0) {
                    bos.write(buff, 0, len);
                }
            }
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    参考资料和推荐阅读:

    [1].https://www.jianshu.com/p/a93348d31d8d
    [2].https://www.jianshu.com/p/da23cf7c1653
    [3].http://www.wjhsh.net/lteal-p-5199911.html
    [4].https://wenku.baidu.com/view/d1e44e4b1db91a37f111f18583d049649b660e9c.html?wkts=1669043878887&bdQuery=Springboot+getOutputStream%28%29+has+already+been+called+for+this+response
    [5].https://blog.csdn.net/weixin_43296313/article/details/125100824

  • 相关阅读:
    关于基环树找环问题
    学不会的博弈论——初级篇
    基于斑马优化的BP神经网络(分类应用) - 附代码
    docker 搭建rknn转换环境
    Diffusion模型
    【Linux】——初识程序地址空间
    营销妙招:链动2+1渠道搭建团队裂变
    2022速卖通宠物用品热销及需求品类推荐!
    Java:类加载机制与与spi的联系
    最大时延扩展、CP 和相干带宽
  • 原文地址:https://blog.csdn.net/xiamaocheng/article/details/127974514