spring前后端下载文件怎么实现?为什么不弹出下载框

后端接口

提供两个接口,一个接口负责生成文件,一个接口负责下载本机文件。
1 生成文件需要前端传入参数,返回给前端生成的文件路径。
2 调用下载接口时,传入文件路径,将文件流返回给前端(放在response里面)。

控制层

    /**
     * 导出文件
     * @param searchRequest
     * @return
     */
    @RequestMapping("/export")
    @ResponseBody
    @BussinessLog(value = "导出数据",module = "嗷呜")
    public Object export(SearchRequest searchRequest){
        String export = service.export(searchRequest);
        return export;
    }
    /**
     * 下载文件
     * @param filepath
     * @return
     */ 
    @RequestMapping("/download")
    @ResponseBody
    @BussinessLog(value = "下载数据",module = "嗷呜")
    public void downloadFile(HttpServletResponse response, @RequestParam("filepath") String filepath){
        service.downloadFile(response,filepath);
    }
    

service层

导出文件的方法

 public String export(SearchRequest search) {
        String type = search.getType();

        Map<String, String> map = new HashMap<String, String>();
        List<String> dataList = new ArrayList<String>();
        // 生成文件的路径
        String dowloadDataPath = dataLocalPath + "downloadData/" + type + "/";
        // 生成文件夹/文件方法
        FileUtil.CreateMultilayerFile(dowloadDataPath);
        dowloadDataPath += type + DateUtil.getAllTime() + ".txt";
        logger.info("dowloadData backPath=" + dowloadDataPath);
        long searchBegin = System.currentTimeMillis();
        
        // 查询数据库,将数据转成list
  		dataList = downloadData(search);
  		
        long searchTime = System.currentTimeMillis() - searchBegin;
        logger.info("download查询数据" + dataList.size() + "条,耗时: " + (searchTime / 1000.0) + "'s!");
        
        TxtUtils.writeTxt(dowloadDataPath, dataList);

        return dowloadDataPath.replace( dataLocalPath + "downloadData/","");
    }

/**
* 写入文件的方法
*/
 public static void writeTxt(String txtPath, List<String> content) {
        FileWriter fileWriter = null;
        File file = new File(txtPath);
        try {
            if (file.exists()) {
                //判断文件是否存在,如果不存在就新建一个txt
                file.createNewFile();
            }
            fileWriter = new FileWriter(file);
            logger.info("开始写入txt文件");
            logger.info("content size=" + content.size());
            for (String tar : content) {
                fileWriter.write(tar);
            }
            fileWriter.flush();
            fileWriter.close();
            logger.info("写入txt文件结束");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

下载文件的方法。

  public void downloadFile(HttpServletResponse response,String filePath) throws IOException {
        File file = new File(filePath);
        // 设置响应头信息
        String filename = file.getName();
        // 设置response的Header
        response.setCharacterEncoding("UTF-8");
        // 指定下载文件名(attachment-以下载方式保存到本地,inline-在线预览)
        response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
        // 告知浏览器文件的大小
        response.addHeader("Content-Length", "" + file.length());
        // 内容类型为通用类型,表示二进制数据流
        response.setContentType("application/octet-stream");
        try(InputStream is = new FileInputStream(file);
            BufferedInputStream bis = new BufferedInputStream(is);
            BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream())){
            byte[] buff = new byte[2048];
            int len;
            while ((len = bis.read(buff)) != -1){
                bos.write(buff, 0, len);
            }
            bos.flush();
        } catch (IOException e){
            throw e;
        }
    }

前端

html部分

展示给用户的只有一个导出按钮,但实际上还有一个隐藏的a标签,是用来弹出下载框的。因为如果只有一个导出按钮,点击这个按钮请求ajax请求,将文件流返回,前端默认不会弹出下载框。ajax是异步请求,没有这个功能。

经过实际验证,点击a标签可以弹出下载文件的按钮。所以我在里面加了一个隐藏的a标签。导出任务完成后,通过js来模拟点击这个a标签,就可以弹出下载框了。

 <div class="layui-inline">
     <a id="downloadFile" hidden="hidden"><span id="downloadSpan">下载</span></a>
     <button id="btnExport" class="layui-btn icon-btn" type="button">导出</button>
</div>

js部分

在导出方法的成功回调方法中,给a标签动态加上重定向的地址。也就是href地址,添加后,调用点击方法。
这里有一个重点:需要调用点击a标签中的span标签
原来我是直接调用的a标签点击,但是死活不出来下载框。我把隐藏属性取消后,手动点击是可以下载的,百思不得其解。查阅各大博文后,在中间加了一个span标签,通过点击这个span,会触发a标签的点击事件。

    TemplateTable.export = function () {
        let queryData = {};
        queryData['timeLimit'] = $("#timeLimit").val();
        queryData['charge'] = charge;
        queryData['fuzzy'] = $('input[name="isFuzzySearch"]:checked').val();

        let ajax = new $ax(Feng.ctxPath + "/export", function (data) {
            $('#downloadFile').attr("href",contextPath + Feng.ctxPath + '/download?filepath='+data);
            $('#downloadSpan').trigger("click");
            Feng.success("成功导出!");
        }, function (data) {
            console.log("data:"+data);
            Feng.error("导出失败!" + data.message + "!");
        });
        ajax.setData(queryData);
        ajax.start();
    };

大功告成
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值