逐渐填充InputStream并用SpringMVC返回
考虑我在数据库中有大量的csv字符串,我需要通过他的请求传递给客户端。
一个天真的方式来做到这一点:
@RequestMapping(value = "/{user}/ejournal", method = RequestMethod.GET, produces = "text/csv") public ResponseEntity<ByteArrayResource> getEJournal(@PathVariable Long userId) { final byte[] documentBody = EJournal .findByUser(userId) .stream() .collect(Collectors.joining("\n")) .getBytes(); return new ResponseEntity( new ByteArrayResource(documentBody), HttpStatus.OK); }
从客户端直接(kotlin代码示例):
val inputStream = eJournalService.getJournal(userId) inputStream.reader().forEachLine { line -> ... }
但是我不得不把所有的数据加载到内存中,然后传递给流,显然效率不高。
所以我需要以某种方式缓冲它使用自定义阅读器分页读取数据和发送缓冲区到客户端。 我想实现我自己的InputStream
但InputStream#read()
返回int
而不是String
,这有点复杂。
任何最佳实践来做到这一点? 我试图搜索,但只有例子传递一个图片使用已经在内存中的流,而不是缓冲分页后批次发送顺序数据库查询。
提前致谢。
从文档
以下是支持的返回类型:
[…]
- 如果方法本身处理响应,则为void(通过直接编写响应内容,为此目的声明ServletResponse / HttpServletResponse类型的参数)
[…]
- 可以返回StreamingResponseBody异步写入响应OutputStream; 也被支持作为ResponseEntity中的主体。
所以你可以做
public StreamingResponseBody getEJournal(@PathVariable Long userId) { return outputStream -> { // write your lines to the outputStream here }; }
您也可以通过将HttpServletResponse
作为方法的参数同步写入流,然后写入其输出流。