Springboot + Vue + axios實現excel的導出下載

後端代碼

pom

       <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-schemas -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>3.17</version>
        </dependency>

controller

 @RequestMapping("downloadExcel")
    @ResponseBody
    public void downloadExcel(HttpServletResponse response){
        try {
            goodService.exportDataToEx(response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

service

 public void exportDataToEx(HttpServletResponse response) throws IOException {
        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet("商品信息表");
        List<Good> goodList = goodMapper.getAllExcelGood();
        // 設置要導出的文件的名字
        SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
        String fileName = "goodinfo"  + sf.format(new Date()) + ".xls";

        // 新增數據行,並且設置單元格數據
        int rowNum = 1;
        // headers表示excel表中第一行的表頭 在excel表中添加表頭
        String[] headers = { "ID", "商品條碼", "名稱", "類型","規格","建議零售價","我的零售價","庫存預警量"};
        HSSFRow row = sheet.createRow(0);
        for(int i=0;i<headers.length;i++){
            HSSFCell cell = row.createCell(i);
            HSSFRichTextString text = new HSSFRichTextString(headers[i]);
            cell.setCellValue(text);
        }
        //在表中存放查詢到的數據放入對應的列
        for (Good item : goodList) {
            HSSFRow row1 = sheet.createRow(rowNum);
            row1.createCell(0).setCellValue(item.getId());
            row1.createCell(1).setCellValue(item.getBarcode());
            row1.createCell(2).setCellValue(item.getTitle());
            row1.createCell(3).setCellValue(item.getTypeid());
            row1.createCell(4).setCellValue(item.getWeight());
            row1.createCell(5).setCellValue(item.getPrice());
            rowNum++;
        }
        response.setContentType("application/octet-stream");
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);
        response.flushBuffer();
        OutputStream outputStream = response.getOutputStream();
        workbook.write(response.getOutputStream());
        outputStream.flush();
        outputStream.close();
    }

Vue前端代碼

      axios({
          method: 'post',
          url:requesturl,
          responseType: 'blob'
        })
      .then(res => {
        const filename = decodeURI(res.headers['content-disposition'].split(';')[1].split('=')[1]) || '商品信息表.xls'
        const blob = new Blob([res.data], {
        type: 'application/octet-stream'
      })
        let url = window.URL.createObjectURL(blob);
        let link = document.createElement('a');
        link.style.display = 'none';
        link.href = url;
        link.setAttribute('download', filename);
        document.body.appendChild(link);
        link.click()
      })

遇到的問題

1.response返回了包含響應頭所帶的所有數據,可以使用console.log(response)查看打印數據,但是打印出來的數據只能拿到默認的響應頭,這裏有個需要注意的地方。

Cache-Control

Content-Language

Content-Type

Expires

Last-Modified

Pragma

如果想讓瀏覽器能訪問到其他響應頭的話,需要後端在服務器上設置Access-Control-Expose-Headers

 response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
 response.setHeader("Content-disposition", "attachment;filename=" + fileName);

這樣response.headers[‘content-disposition’].split(’;’)[1].split(’=’)[1] 就能取到接口返回的文件名稱了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章