Vue +springboot 导出excel

本文介绍两种前后端分离环境下导出Excel的方法:1. 前端使用xlsx解析JSON生成Excel;2. 后台返回文件流。涵盖具体代码实现及解决跨域问题。

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

两种实现方式:1.后台返回json,前台通过xlsx解析,然后生成excel文件;2.后台返回文件流;

第一种方式:贴出前台代码,后台的就不需要了吧,就是很简单的json数据;

 //导出
      exportTable() {
        var jsono = [{
          "应用名字" : "appname",
          "关键字" : "keyword",
          
         
        }]
        var keyMap = []; 
        var valueMap = [];
        var list1 = []
        for (var k in jsono[0]) {
            keyMap.push(k)
            valueMap.push(jsono[0][k])
        }
        for (var i=0;i<this.dataList.length;i++) {      
            list1[i] = []
            
            for (var j in valueMap) {
              
                list1[i][keyMap[j]]= this.dataList[i][valueMap[j]]   
                     
            }          
        }
        var ws = xlsx.utils.json_to_sheet(list1);
        var wb = xlsx.utils.book_new();
        xlsx.utils.book_append_sheet(wb, ws, "People");//sheet名称
        let out = xlsx.write(wb, {
          bookType: "xlsx",
          bookSST: true,
          type: "array"
        });
        try {
          fileSaver.saveAs(
            new Blob([out], {
              type: "application/octet-stream"
            }),
            "列表.xlsx"
          );
        } catch (e) {
          // 错误处理方式
        }
        return out;
      },

第二种:同样,先贴出前台代码:

// 导出方法

exportTable(){
    this.$http({
        url: this.$http.adornUrl('/*/getExportData'),//获取文件流的接口路径
        method: 'post',
        data: {//请求参数
            "id":"12"
            },    
    responseType: 'blob' // 表明返回服务器返回的数据类型 很重要!!
    }).then((res) => {
        //将文件流转成blob形式
        const blob = new Blob([res.data],{type: 'application/vnd.ms-excel'});
        let filename ='1.xls';
        //创建一个超链接,将文件流赋进去,然后实现这个超链接的单击事件
        const elink = document.createElement('a');
        elink.download = filename;
        elink.style.display = 'none';
        elink.href = URL.createObjectURL(blob);
        document.body.appendChild(elink);
        elink.click();
        URL.revokeObjectURL(elink.href); // 释放URL 对象
        document.body.removeChild(elink);
    }).catch(error => {
        this.$message.error('导出失败');
        // console.log(error)

    })

},

后台代码我不想贴了,因为用的jxl的技术,很老,我就只贴出遇到的问题跟解决方式吧:
(1)第一个问题:前台不识别文件流

        responseType: 'blob' // 表明返回服务器返回的数据类型 很重要!!

    这个一定要加在请求头里面,否则识别不了文件流

(2)第二个问题:跨域

因为是前后端分离,IP跟端口肯定不一样,浏览器不接受这种跨域返回的文件流,所以需要在response的header里面加一条属性:

response.setHeader("Access-Control-Allow-Origin", "http://***:8001");//解决跨域

网上有很多说放个*就行,像这样:

response.setHeader("Access-Control-Allow-Origin", "*");//解决跨域

但是我这试了不行,所以就把前台的具体IP跟端口写进去了,反正是管用。

 

//费了很大功夫,把后台返回文件流的代码更新成poi方式了,然后我发现,后台jxl方式,需要解决跨域,而改成poi就不需要跨域了,很神奇,也没空去了解更多;先把后台代码记录一下:

public static void export(List<Map<String,Object>> list, LinkedHashMap<String, String> fieldMap,String filName,
                       HttpServletResponse response) throws IOException {
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet(filName+"1");//新建sheet
        HSSFCellStyle contextstyle =wb.createCellStyle();
        HSSFRow row = null;
        int rowIndex = 0 ;
        row = sheet.createRow(0);
        row.setHeight((short) (22.50 * 20));//设置行高
        // 定义存放英文字段名和中文字段名的数组
        String[] enFields = new String[fieldMap.size()];
        String[] cnFields = new String[fieldMap.size()];
        // 填充数组
        int count = 0;
        for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
            enFields[count] = entry.getKey();

            cnFields[count] = entry.getValue();
            count++;
        }
        //设置表头
        for(int i=0; i<cnFields.length;i++){
            row.createCell(i).setCellValue(cnFields[i]);
        }
        for (int i = 0; i < list.size(); i++) {
            if(rowIndex>65535 ){
                sheet = wb.createSheet(filName+"2");
                row = sheet.createRow(0);
                row.setHeight((short) (22.50 * 20));//设置行高
                //设置表头
                for(int k=0; k<cnFields.length;k++){
                    row.createCell(k).setCellValue(cnFields[k]);
                }
            }
            row = sheet.createRow(i + 1);
            for(int j = 0; j<enFields.length;j++) {
                Object data = list.get(i).get(enFields[j]);//获取第i行第j列所放数据
                HSSFCell contentCell = row.createCell(j);
                boolean isNum = false;
                boolean isInteger = false;
                if (data != null || "".equals(data)) {
                    //判断data是否为数值型
                    isNum = data.toString().matches("^(-?\\d+)(\\.\\d+)?$");
                    //判断data是否为整数(小数部分是否为0)
                    isInteger=data.toString().matches("^[-\\+]?[\\d]*$");
                }
                if(isNum){
                    HSSFDataFormat df = wb.createDataFormat(); // 此处设置数据格式
                    if (isInteger) {
                        //数据格式只显示整数
                        contextstyle.setDataFormat(df.getBuiltinFormat("0"));
                        // 设置单元格内容为double类型
                        contentCell.setCellValue(data.toString());
                    }else{
                        //保留两位小数点
                        contextstyle.setDataFormat(df.getBuiltinFormat("0.00"));
                        // 设置单元格内容为double类型
                       contentCell.setCellValue(Double.parseDouble(data.toString()));
                        // 设置单元格格式
                        contentCell.setCellStyle(contextstyle);
                    }
                }else {
                    contentCell.setCellValue(list.get(i).get(enFields[j]) == null ? "" : list.get(i).get(enFields[j]).toString());
                }
            }
            rowIndex++;
        }
        // 遍历集合数据,产生数据行
        sheet.setDefaultRowHeight((short) (16.5 * 20));
        //列宽自适应
        for (int i = 0; i <= 13; i++) {
            sheet.autoSizeColumn(i);
        }
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        OutputStream os = response.getOutputStream();
        response.setHeader("Content-disposition", "attachment;filename=balancelog.xls");//默认Excel名称
        wb.write(os);
        os.flush();
        os.close();
    }

 

### 实现 Vue 和 Spring Boot 中的 Excel 表格导入导出功能 #### 后端 (Spring Boot) 为了高效地处理Excel数据,在Spring Boot项目中选择了阿里巴巴开源的EasyExcel库来简化操作过程[^1]。 ##### 导入功能实现 在控制器层,创建用于接收上传文件的方法: ```java @PostMapping("/import_excel") public ResponseEntity<String> importExcel(@RequestParam("file") MultipartFile file) { try { EasyExcel.read(file.getInputStream(), SysUser.class, new PageReadListener<SysUser>(dataList -> { // 处理读取的数据并保存到数据库或其他存储方式 sysUserService.saveBatch(dataList); })).sheet().doRead(); return ResponseEntity.ok("Import successful"); } catch (Exception e) { e.printStackTrace(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Failed to import data."); } } ``` ##### 导出功能实现 同样是在控制器层设置导出接口,以便能够响应来自前端页面发起的请求[^2]: ```java @GetMapping("/export_excel") public void exportExcel(HttpServletResponse response) throws IOException { List<Map<String, Object>> list = sysUserService.getUserData(); // 获取要导出的数据 String fileName = URLEncoder.encode("user_data", "UTF-8").replaceAll("\\+", "%20");; response.setContentType("application/vnd.ms-excel;charset=utf-8"); response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx"); WriteSheet writeSheet = EasyExcel.writerSheet("users").build(); EasyExcel.write(response.getOutputStream()).excelType(ExcelTypeEnum.XLSX) .head(head())// 设置表头 .sheet("用户信息") .doWrite(list.stream() .map(map -> map.values().toArray(new Object[0])) .collect(Collectors.toList())); } private List<List<String>> head() { return Arrays.asList( Collections.singletonList("ID"), Collections.singletonList("用户名"), Collections.singletonList("邮箱地址")); } ``` 对于配置文件中的路径指定可以按照如下方式进行设定[^3]: ```yaml # application.yml spring: excel: file: path: D:/user_info_excel/ ``` #### 前端 (Vue.js) 在Vue应用里构建一个简单的界面让用户可以选择文件进行上传以及点击按钮触发下载动作: ```html <template> <div class="upload-container"> <input type="file" id="fileInput" ref="fileInput"/> <button v-on:click="handleUpload">上传</button> <a :href="downloadUrl" download="user_data.xlsx"><button>下载模板</button></a> </div> </template> <script> export default { name: 'FileUploader', methods: { handleUpload () { const formData = new FormData(); formData.append('file', this.$refs.fileInput.files[0]); fetch('/api/import_excel', { method: 'POST', body: formData, }) .then(res => res.json()) .then((result) => console.log(result)) .catch(error => console.error('Error:', error)); }, getDownloadLink(){ return `${process.env.VUE_APP_API_URL}/export_excel`; } }, computed:{ downloadUrl(){ return this.getDownloadLink(); } } }; </script> ``` 上述代码片段展示了如何利用Vue框架配合HTML5特性完成基本的功能需求。需要注意的是实际开发过程中还需要考虑安全性验证等问题
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值