我试图读取Excel文件以对其进行操作或向其中添加新数据并写回。我也正在尝试使用Flux和Mono完成一个完整的反应过程。想法是通过Web服务返回结果文件或字节数组。
我的问题是如何以非阻塞方式获取InputStream和OutputStream?
我正在使用Apache Poi库读取并生成Excel文件。
我目前有一个基于Mono.fromCallable()和阻塞代码来获取输入流的解决方案。
例如,Web服务部分如下。
@GetMapping(value = API_BASE_PATH + "/download", produces = "application/vnd.ms-excel")
public Mono<ByteArrayResource> download() {
Flux<TimeKeepingEntry> createExcel = excelExport.createDocument(false);
return createExcel.then(Mono.fromCallable(() -> {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
excelExport.getWb().write(outputStream);
return new ByteArrayResource(outputStream.toByteArray());
}).subscribeOn(Schedulers.elastic()));
}
文件处理:
public Flux<TimeKeepingEntry> createDocument(boolean all) {
Flux<TimeKeepingEntry> entries = null;
try {
InputStream inputStream = new ClassPathResource("Timesheet Template.xlsx").getInputStream();
wb = WorkbookFactory.create(inputStream);
Sheet sheet = wb.getSheetAt(0);
log.info("Created document");
if (all) {
//all entries
} else {
entries = service.findByMonth(currentMonthName).log("Excel Export - retrievedMonths").sort(Comparator.comparing(TimeKeepingEntry::getDateOfMonth)).doOnNext(timeKeepingEntry-> {
this.populateEntry(sheet, timeKeepingEntry);
});
}
} catch (IOException e) {
log.error("Error Importing File", e);
}
return entries;
}
这很好用,但与Flux和Mono不太吻合。这里的一些指导会很好。我希望整个序列都不会阻塞。
答案 0 :(得分:0)
很遗憾,WorkbookFactory.create()
操作正在阻塞,因此您必须使用命令式代码执行该操作。但是,每次都能获取KeepingEntry都是反应性的。您的代码如下所示:
public Flux<TimeKeepingEntry> createDocument() {
return Flux.generate(
this::getWorkbookSheet,
(sheet, sink) -> {
sink.next(getNextTimeKeepingEntryFrom(sheet));
},
this::closeWorkbook);
}
这会将工作簿保留在内存中,但是当请求Flux的元素时将按需获取每个条目。