我有一个非常基本的基于SpringBoot
和Thymeleaf
的应用程序,并与Oracle DB
绑定。
我的应用程序当前正在读取一个表,并通过Controller
和Thymeleaf
UI模板将其显示在页面上。我在此表底部还有一个链接,上面写着"Export to Excel"
,该链接调用服务层中的方法,并成功生成甚至下载该.XLS
文档。
但是,问题是生成的excel是页面上内容的精确副本(右侧有一些额外的空列),即使我通过编写代码手动创建了工作表也添加了额外的列,另一个标题。
不确定为什么我的代码没有被调用,为什么我的HTML表数据只是按原样导出到excel工作表中。
ExcelReportController.java
@Controller
@Log4j2
public class ExcelReportController {
private static final String EXCEL_FILE_NAME = "applications.xls";
@Autowired
private LinkApplService linkApplService;
@GetMapping("/excel")
public ModelAndView showPage() {
return new ModelAndView("applications", "linkAppls", linkApplService.getAllLinkAppls());
}
@GetMapping("/download")
public ModelAndView download(HttpServletResponse response) {
response.setHeader("Content-disposition", "attachment; filename=" + EXCEL_FILE_NAME);
return new ModelAndView("applications", "linkAppls", linkApplService.getAllLinkAppls());
}
}
ExcelBuilderService.java
@Service
public class ExcelBuilderService extends AbstractXlsView {
@Override
protected void buildExcelDocument(Map<String, Object> model, Workbook workbook, HttpServletRequest request,
HttpServletResponse response) {
Iterable<LinkAppl> linkAppls = (Iterable<LinkAppl>) model.get("linkAppls");
//THIS SHEET WITH TITLE NOT GETTING SHOWN
Sheet sheet = workbook.createSheet("All Applications List");
Row header = sheet.createRow(0);
header.createCell(0).setCellValue("ID");
header.createCell(1).setCellValue("DESC");
header.createCell(2).setCellValue("DESC");
header.createCell(3).setCellValue("LINK_NOTES"); //THIS COLUMN NOT GETTING DISPLAYED
int rowNum = 1;
for (LinkAppl la : linkAppls) {
Row row = sheet.createRow(rowNum++);
row.createCell(0).setCellValue(la.getApplId());
row.createCell(1).setCellValue(la.getApplDeTx());
row.createCell(2).setCellValue(la.getApplActvCd());
row.createCell(3).setCellValue(la.getLinkNotesTx());
}
}
}
LinkAppl.java
@Entity
@Table(name = "LINK_APPL")
public class LinkAppl {
private String applId;
private String applDeTx;
private String seqNbResetCd;
private String intfMsgFrmtCd;
private String sndRcvCd;
private String applAcptMsgFrmtCd;
private String applActvCd;
private String sodEodIn;
private String linkNotesTx;
private String lastModByUsrId;
private Timestamp lastModTs;
private String sndCnctStsCd;
private Long maxSeqNb;
private String batIntfIn;
private String gfpSrcSiteCd;
private String rcvRterAckmentIn;
private String rcvMqCodIn;
private String fxApplIn;
private String rcvEodpAckmentIn;
//getters and setters go here
}
applications.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Link Statistics Report</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h4>Excel Generation Demo</h4>
<table border="1">
<thead>
<tr>
<td>App ID</td>
<td>Name</td>
<td>Active</td>
</tr>
</thead>
<tbody>
<tr th:each="a : ${linkAppls}">
<td th:text="${a.applId}">App ID</td>
<td th:text="${a.getApplDeTx()}">Description</td>
<td th:text="${a.applActvCd}">Active</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="7">
<a href="/download">Export to Excel</a>
</td>
</tr>
</tfoot>
</table>
</body>
</html>
pom.xml
<!-- for handling .xls files (older format) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.1</version>
</dependency>
<!-- for handling .xlsx files (newer format) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.1</version>
</dependency>
答案 0 :(得分:1)
控制器中的两个ModelAndView完全相同。
return new ModelAndView("applications", "linkAppls", linkApplService.getAllLinkAppls());
在下载控制器中完全相同:
return new ModelAndView("applications", "linkAppls", linkApplService.getAllLinkAppls());
设置content-disposition
不会改变spring处理请求的方式,如果您在文本编辑器中打开applications.xls
,您会发现您刚刚下载了html页面重命名为.xls
文件。您需要弄清楚如何正确连接并使用您创建的AbstractXlsView
。
下载文件:
@GetMapping("/download")
public void download(HttpServletResponse response) throws Exception {
Iterable<LinkAppl> linkAppls = linkApplService.getAllLinkAppls();
Workbook workbook = new HSSFWorkbook();
Sheet sheet = workbook.createSheet("All Applications List");
Row header = sheet.createRow(0);
header.createCell(0).setCellValue("ID");
header.createCell(1).setCellValue("DESC");
header.createCell(2).setCellValue("DESC");
header.createCell(3).setCellValue("LINK_NOTES");
int rowNum = 1;
for (LinkAppl la : linkAppls) {
Row row = sheet.createRow(rowNum++);
row.createCell(0).setCellValue(la.getApplId());
row.createCell(1).setCellValue(la.getApplDeTx());
row.createCell(2).setCellValue(la.getApplActvCd());
row.createCell(3).setCellValue(la.getLinkNotesTx());
}
response.setHeader("Content-disposition", "attachment; filename=" + EXCEL_FILE_NAME);
workbook.write(response.getOutputStream());
}
答案 1 :(得分:0)
因此,在@Metroids的大力帮助下,我终于能够通过控制器下载Excel文件。我还尝试下载src / main / resources文件夹中的现有文件。这是用于更好理解的源代码。
applications.html
<a href="/download">Export to Excel</a>
<a href="/buildNDownload">Export to Excel 2</a>
ExcelReportController.java
@Controller
@Log4j2
public class ExcelReportController {
private static final String EXCEL_FILE_NAME = "applications.xls";
@Autowired
private LinkApplService linkApplService;
@GetMapping("/excel")
public ModelAndView showPage() {
return new ModelAndView("applications", "linkAppls", linkApplService.getAllLinkAppls());
}
@GetMapping(value = "/download")
public void download(HttpServletResponse response) {
response.addHeader("Content-Disposition", "attachment; filename=" + EXCEL_FILE_NAME);
try {
//download an existing file located in src/main/resources folder
File file = ResourceUtils.getFile("classpath:" + EXCEL_FILE_NAME);
InputStream inputStream = new FileInputStream(file);
IOUtils.copy(inputStream, response.getOutputStream());
response.flushBuffer();
inputStream.close();
} catch (IOException e) {
log.error("Error while locating file", e);
}
}
@GetMapping(value = "/buildNDownload")
public void buildNDownload(HttpServletResponse response) throws IOException {
response.setHeader("Content-disposition", "attachment; filename=applications_new.xlsx");
Iterable<LinkAppl> linkAppls = linkApplService.getAllLinkAppls();
//build a file from scratch and then download
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("All Applications List");
Row header = sheet.createRow(0);
header.createCell(0).setCellValue("ID");
header.createCell(1).setCellValue("DESC");
header.createCell(2).setCellValue("ACTIVE");
header.createCell(3).setCellValue("LINK_NOTES");
int rowNum = 1;
for (LinkAppl la : linkAppls) {
Row row = sheet.createRow(rowNum++);
row.createCell(0).setCellValue(la.getApplId());
row.createCell(1).setCellValue(la.getApplDeTx());
row.createCell(2).setCellValue(la.getApplActvCd());
row.createCell(3).setCellValue(la.getLinkNotesTx());
}
workbook.write(response.getOutputStream());
}
}
pom.xml
<!-- for handling .xls files (older format) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.1</version>
</dependency>
<!-- for handling .xlsx files (newer format) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>