使用Spring Boot Controller返回Excel文件

时间:2018-08-22 10:11:43

标签: excel spring-boot

我试图在Spring Boot中创建一个休息端点,该端点从DB读取数据,生成一个excel文件(使用Apache POI),并使用HttpServletResponse返回给用户,但是当我调用此文件时,会创建excel,但不是下载。我之前有一些其他代码可以正常工作,但是我不小心删除了这些代码,但是现在我陷入了困境。任何帮助/线索都表示赞赏。

@RequestMapping(path = "/save", method = RequestMethod.GET)
public ResponseEntity<String> saveToXls(@RequestParam String id, @RequestParam String appName, HttpServletResponse response) {
    AppInstance appInstance = appInstanceRepo.get(id);
    List<DownloadDetail> downloadDetailList = downloadDAO.searchByInstanceId(id);
    //List<DownloadDetail> downloadDetailList = appInstance.getDownloads();
    System.out.print("LIST SIZE:" + downloadDetailList.size());
    String fileName = appName + " report";
    File myFile = new File(fileName + ".xls");

    FileOutputStream fileOut;
    downloadDetailList.forEach(downloadDetail -> System.out.print(downloadDetail.getSid()));
    try {

        try (HSSFWorkbook workbook = new HSSFWorkbook()) {
            HSSFSheet sheet = workbook.createSheet("lawix10");
            HSSFRow rowhead = sheet.createRow((short) 0);
            rowhead.createCell((short) 0).setCellValue("SID");
            rowhead.createCell((short) 1).setCellValue("Download Time");
            rowhead.createCell((short) 2).setCellValue("OS Version");
            int i = 0;

            for (DownloadDetail downloadDetail : downloadDetailList) {
                System.out.print("In loop -2");
                HSSFRow row = sheet.createRow((short) i);
                row.createCell((short) 0).setCellValue(downloadDetail.getSid());
                row.createCell((short) 1).setCellValue(downloadDetail.getDownloadTime());
                row.createCell((short) 2).setCellValue(downloadDetail.getOsVersion());
                i++;
            }
            fileOut = new FileOutputStream(myFile);
            workbook.write(fileOut);
        }
        fileOut.close();

        byte[] buffer = new byte[10240];
        response.addHeader("Content-disposition", "attachment; filename=test.xls");
        response.setContentType("application/vnd.ms-excel");
        try (
                InputStream input = new FileInputStream(myFile);
                OutputStream output = response.getOutputStream();
        ) {
            for (int length = 0; (length = input.read(buffer)) > 0;) {
                output.write(buffer, 0, length);
            }
        }

        response.flushBuffer();

    } catch (FileNotFoundException e1) {
        e1.printStackTrace();
    } catch (IOException e1) {
        e1.printStackTrace();
    }


    return null;
}

编辑: 我试图用另一种方式做到这一点,如下所示:

        try (InputStream is = new FileInputStream(myFile)) {
            response.addHeader("Content-disposition", "attachment; filename=test.xls");
            response.setContentType("application/vnd.ms-excel");
            IOUtils.copy(is, response.getOutputStream());

        }
    response.flushBuffer();

这似乎也没有削减。

3 个答案:

答案 0 :(得分:0)

这是我的例子。问题可能出在您如何管理OutputStream:

ServletOutputStream os = response.getOutputStream();
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment; filename=\""+fileName+".xls\"");

workbook = excelStrategyMap.get(strategy).export(idList, status, params);

workbook.write(os);
workbook.close();
os.flush();

response.flushBuffer(); 

答案 1 :(得分:0)

一旦获得工作簿文件,请设置文件名和文件类型。并添加如下所述的响应标头和内容类型。

然后将文件写入响应并刷新其缓冲区。

        XSSFWorkbook file = excelUploadService.downloadDocument();
        String filename = "Export.xlsx";
        String filetype = "xlsx";
        response.addHeader("Content-disposition", "attachment;filename=" + filename);
        response.setContentType(filetype);
        // Copy the stream to the response's output stream.

        file.write(response.getOutputStream());
        response.flushBuffer();

在客户端,从REST API获取响应,并设置响应对象接收的内容类型。使用FileSaver库将文件保存到本地文件系统中。

这是FileSaver js的文档-File saver JS Library

        var type = response.headers("Content-Type");
        var blob = new Blob([response.data], {type: type});

        saveAs(blob, 'Export Data'+ '.xlsx');

答案 2 :(得分:0)

@GetMapping(value = "/", produces = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
@ResponseBody
public byte[] generateExcel() {
        byte[] res = statisticsService.generateExcel();
        return res;