阿风啦的gravatar头像
阿风啦 2021-07-31 11:41:48
vue使用原生js做下载,一个月实习生活的总结,内附后台demo源码

大家好呀,最近工作中遇到的问题,给大家做一个分享和记录。截止到九月开学,我还是一个大三的学生,所以呢,我目前还是一个练习时长一个月的开发实习生。很幸运,我到的项目组是使用开源框架开发的,就是vue + Spring Boot,我其他实习生同事被分到了老项目,还是jsp、servlet哪些东西,还会在页面里面写Java代码,确实有点……

 

虽然用到了 vue + Spring Boot ,但是呢全是用的公司的框架,就像vue,平时查看用法去vue.js官网看就行,我们公司呢,也有一个官网,上面是前端框架用法,当然呢,这个网站没有发布,得连公司内网才能访问。跟vue用法一样,有vue基础几乎都能看懂“大致意思”,看懂归看懂,自己想写还得多努力几天的哈;还有那个Spring Boot也是不常规的,就是跟我们平时在学校和在网课上看的不一样,也是公司框架┭┮﹏┭┮,有基础的话,多努力努力,做个增删改查还是上手很快的O(∩_∩)O,希望让一些还没有去工作的牛牛有一定的了解。多学习一下:SQL 、VUE 、Spring Boot ,当然为了过面试那关,还得多学习一些其他知识的。

 

(注:我是一个学后端的,但是来公司了,前后端都得写,毕竟是个搞web开发的,Html和css不可能一点不会,但是……懂得都懂┭┮﹏┭┮)

 

好的,正文开始(源码在最后):

 

目的是要用vue和后台做一个下载功能,我们平时前端调用后端一般都是使用axios,但是axios无法实现下载功能,所以我想到了,原生js,当然axios也有解决方法,大家可以自行百度了解。

 

下载Excel表格,后端呢,我知道两种方法:阿里的EasyExcel ,和阿帕奇的poi

 

easyExcel官网:https://www.yuque.com/easyexcel/doc/easyexcel (汉化,易懂)

 

里面有文件下载的例子,我就不粘过来了

 

poi : https://poi.apache.org/components/spreadsheet/quick-guide.html#ReadWriteWorkbook

 

其实下载功能我们都是用的:esponse中的OutputStream进行文件下载

一个下载小例子:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//使用response获得字节输出流
		ServletOutputStream out=response.getOutputStream();
		
		//获得服务器上面的图片
		String realpath=this.getServletContext().getRealPath("456.png");
		InputStream in=new FileInputStream(realpath);
		int len=0;
		byte[] buffer=new byte[1024];
		while((len=in.read(buffer))>0){
			out.write(buffer,0,len);
		}
		in.close();
		out.close();	
	}

 

下面就是我的源码,两种都有,注解详细:

easyexcel不要忘记,实体类哟,根据实体类上注解生成表格列名:

public class User extends BaseRowModel {
    // 主键id
    @ExcelIgnore // 生成报表时忽略,不生成次字段
    private Integer id;

    @ExcelProperty(value = "姓名", index = 0) // 定义表头名称和位置,0代表第一列
    private String name;

    @ExcelProperty(value = "年龄", index = 1)
    private Integer age;

    @ColumnWidth(20) // 定义列宽
    @DateTimeFormat(value = "yyyy/MM/dd")
    @ExcelProperty(value = "出生日期", index = 2)
    private Date birthday;
}
/*easyExcel导出*/
    @RequestMapping(value = "/exportExcel")
    public void exportExcel(HttpServletResponse response) throws IOException {
        //设置编码与文件类型
        response.setContentType("mutipart/form-data");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition","attachment;filename=test.xlsx");
        ServletOutputStream out=response.getOutputStream();
        //导出的数据
        List<User> users = userService.findAll();
        //导出并下载
        EasyExcel.write(out,User.class).sheet("test").doWrite(users);
        out.flush();
        out.close();
    }

poi:

    //poi生成xls文件并下载
    @GetMapping("/download")
    public void download(HttpServletResponse response){
        response.setContentType("application/binary;charset=UTF-8");
        try{
            ServletOutputStream out=response.getOutputStream();
            //文件名
            String name = "扫描榜单下载";
            try {
                //设置文件头:最后一个参数是设置下载文件名
                response.setHeader("Content-Disposition", "attachment;fileName=" +
                        URLEncoder.encode(name+".xls", "UTF-8"));
            } catch (UnsupportedEncodingException e1) {
                e1.printStackTrace();
            }
            //表格的列的标题
            String[] titles = { "姓名","年龄","出生日期" };
            //表格的数据,这里是查询,因为是例子,我做的查询全部,可自定义
            List<User> tops = userService.findAll();
            export(tops,titles, out);
        } catch(Exception e){
            e.printStackTrace();
        }
    }
    //转成.xls文件
    public void export(List<User> tops,String[] titles, ServletOutputStream out) throws Exception{
        try{
            // 第一步,创建一个workbook,对应一个Excel文件
            HSSFWorkbook workbook = new HSSFWorkbook();
            //表名
            String sheetName="扫描榜单";
            // 第二步,在webbook中添加一个sheet,对应Excel文件中的sheet
            HSSFSheet hssfSheet = workbook.createSheet(sheetName);

            // 第三步,在sheet中添加表头第0行(表头),注意老版本poi对Excel的行数列数有限制short

            HSSFRow row = hssfSheet.createRow(0);
            // 第四步,创建单元格,并设置值表头 设置表头居中
            HSSFCellStyle hssfCellStyle = workbook.createCellStyle();

            //居中样式
            hssfCellStyle.setAlignment(HorizontalAlignment.CENTER);
            //创建列
            HSSFCell hssfCell = null;
            for (int i = 0; i < titles.length; i++) {
                hssfCell = row.createCell(i);//列索引从0开始
                hssfCell.setCellValue(titles[i]);//列名1
                hssfCell.setCellStyle(hssfCellStyle);//列居中显示
            }
            /*把要导入的值放到一个二维数组中,表格正好对应二维数组*/
            String[][] dataList =new String[tops.size()][3];
            //将日期类型转换成字符串类型
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
            for(int i=0;i<tops.size();i++){
                dataList[i][0]=tops.get(i).getName();
                dataList[i][1]=String.valueOf(tops.get(i).getAge());
                //日期类型格式化成字符型
                dataList[i][2]=sdf.format(tops.get(i).getBirthday());
            }

            //把表格内容加入,从第二行开始
            for(int i=0;i<dataList.length;i++){
                row=hssfSheet.createRow(i+1);
                for(int j=0;j<3;j++){
                    row.createCell(j).setCellValue(dataList[i][j]);
                }
            }

            // 第七步,将文件输出到客户端浏览器
            try {
                workbook.write(out);
                out.flush();
                out.close();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }catch(Exception e){
            e.printStackTrace();
            throw new Exception("导出信息失败!");

        }
    }

 

当然第一步都是先导依赖哈

 

<!--导出导入easyexcel-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.1.4</version>
        </dependency>
        <!-- org.apache.poi/poi -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>

然后就是原生js发送post请求:

<button onclick="send()">测试</button>

<script>
    function post(url, params) {
        var temp = document.createElement("form");
        temp.action = url;
        temp.method = "post";
        temp.style.display = "none";
        for ( var x in params) {
            var opt = document.createElement("input");
            opt.name = x;
            opt.value = params[x];
            temp.appendChild(opt);
        }
        document.body.appendChild(temp);
        temp.submit();
        return temp;
    }
    //调用post方法,发送请求,只是例子,age写死了
    function send() {
        post(
            "http://127.0.0.1:8080/user/download",
            {
                age : 23
            });
    }
</script>

AJAX无法下载文件的原因

下载其实是浏览器的内置事件,浏览器的 GET请求(frame、a)、 POST请求(form)具有如下特点:

response会交由浏览器处理

response内容可以为二进制文件、字符串等

但是AJAX请求不一样

response会交由 Javascript 处理

response内容只能接收字符串才能继续处理

因此,AJAX本身无法触发浏览器的下载功能。

 

最后在vue中整合:

//下载,调用post请求
      download() {
        this.post({
          pageNumber: this.pageNumber,
          pageSize: this.pageSize,
          sonarState: this.appState,
          appName: this.searchContent,
          roleName: this.roleName
        });
      },
      //发送post请求
      post( params){
        var form = document.createElement("form");
        form.style.display = "none";
        form.action = 'http://localhost:8090/download';
        form.method = "post";
        document.body.appendChild(form);

        for (var key in params) {
          var input = document.createElement("input");
          input.type = "hidden";
          input.name = key;
          input.value = params[key];
          form.appendChild(input);
        }

        form.submit();
        form.remove();
        return form;
      },

后台demo下载:

链接:https://pan.baidu.com/s/1lGlE1qrN7oFSlbDsfCtBRQ 
提取码:o0ud


打赏

已有1人打赏

最代码官方的gravatar头像
最近浏览
暂无贡献等级
luolukka  LV8 2023年1月2日
187236  LV4 2022年11月17日
weixiao  LV6 2022年10月23日
最代码_码鑫源  LV6 2022年10月17日
hunan27  LV11 2022年10月10日
qqmini 2022年8月31日
暂无贡献等级
szy0077  LV4 2022年7月21日
奥术大师大所da 2022年7月7日
暂无贡献等级
406503223  LV5 2022年7月1日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友