spring-boot - 生成 PDF / XLSX 文件作为 REST API 的附件
问题描述
要求是在点击 REST API 端点时生成 pdf / excel 文档。即 localhost:8080/download.xlsx -> 生成数据为 .xlsx 格式的文件 localhost:8080/download.pdf -> 生成数据为 .pdf 格式的文件
Spring Boot 版本 - 2.0.2
由于我使用的是 Spring Boot 相对较新的版本,因此我必须实现 WebMvcConfigurer 而不是扩展 WebMvcConfigurerAdapter
我正在配置 ContentNegotiatingViewResolver
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer
configurer) {
configurer
.favorPathExtension(true)
.defaultContentType(MediaType.APPLICATION_JSON);
}
@Bean
public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager
manager) {
ContentNegotiatingViewResolver resolver = new
ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager(manager);
// Define all possible view resolvers
List<ViewResolver> resolvers = new ArrayList<>();
resolvers.add(excelViewResolver());
resolvers.add(pdfViewResolver());
resolver.setViewResolvers(resolvers);
return resolver;
}
@Bean
public ViewResolver excelViewResolver() {
return new ExcelViewResolver();
}
@Bean
public ViewResolver pdfViewResolver() {
return new PdfViewResolver();
}
在我的控制器中: -
@Controller
public class MyController{
@PostMapping(value = "/download", produces = {"application/pdf",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"})
public String downloadData(Model model, @RequestBody
someRequestView requestView) {
getSpringVersion();
model.addAttribute("someResultList",
someService.extractDataForDownload(requestView));
return "";
}
}
我什么都试过了,但是当我点击 localhost:8080/download.pdf -> 它给了我 404 not found 。请提出解决此问题的方法。
解决方案
ExcelViewResolver 在最新版本中已被弃用。下面是一个以简单方式生成 Excel 文档的示例。
首先,创建一个 Excel 生成器类。根据要求配置列。并从数据库表中检索数据。
下面是示例 excel 生成器类。
public class StateExcelGenerator {
public static ByteArrayInputStream statesToExcel(List<State> states) throws IOException {
String[] COLUMNs = { "Id", "Name", "Desc" };
try (Workbook workbook = new HSSFWorkbook(); ByteArrayOutputStream out = new ByteArrayOutputStream();) {
CreationHelper createHelper = workbook.getCreationHelper();
Sheet sheet = workbook.createSheet("StateInfo");
Font headerFont = workbook.createFont();
headerFont.setBold(true);
headerFont.setColor(IndexedColors.BLUE.getIndex());
CellStyle headerCellStyle = workbook.createCellStyle();
headerCellStyle.setFont(headerFont);
// Row for Header
Row headerRow = sheet.createRow(0);
// Header
for (int col = 0; col < COLUMNs.length; col++) {
Cell cell = headerRow.createCell(col);
cell.setCellValue(COLUMNs[col]);
cell.setCellStyle(headerCellStyle);
}
// CellStyle for Age
CellStyle ageCellStyle = workbook.createCellStyle();
ageCellStyle.setDataFormat(createHelper.createDataFormat().getFormat("#"));
int rowIdx = 1;
for (State state : states) {
Row row = sheet.createRow(rowIdx++);
row.createCell(0).setCellValue(state.getId());
row.createCell(1).setCellValue(state.getName());
row.createCell(2).setCellValue(state.getDesc());
}
workbook.write(out);
return new ByteArrayInputStream(out.toByteArray());
}
}
}
现在修改您的控制器以处理下载文件,如下所示。
@Controller
@RequestMapping("/admin/state")
public class StateController {
@RequestMapping(value = "/download/statedata.xlsx", method = RequestMethod.GET)
public ResponseEntity<InputStreamResource> excelCustomersReport() throws IOException {
List<State> states = stateService.getData();
ByteArrayInputStream in = StateExcelGenerator.statesToExcel(states);
// return IOUtils.toByteArray(in);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment; filename=customers.xlsx");
return ResponseEntity.ok().headers(headers).body(new InputStreamResource(in));
}
}
现在在您的视图页面中创建一个超链接,例如 jsp 文件,以访问上述控制器方法。
<a href="/admin/state/download/statedata.xlsx">Click here to download the file</a>
下面是下载的excel文件。
推荐阅读
- python - 使字典无法正常工作的功能
- azure - 连接尝试失败,因为连接方在一段时间后没有正确响应,或者建立连接失败
- python - 无法在 django 中为 CustomUser 模型分配 SimpleLazyObject
- javascript - 单击菜单项 js
- html - HTML - rowspan="2" 什么都不做,而 rowspan="3" 完美运行
- vue.js - 我认为方法不是反应性的,但为什么在这个例子中方法是反应性的?
- web-services - 做什么
错误处理输入 尝试使用 PL/SQL 调用 web 服务时是什么意思? - lazarus - Lazarus IDE 表格大小
- python - Django - 未调用信号接收器
- sql - 使用 PL/SQL,如何创建触发器以根据字符长度验证字段?