我是Spring 5和Reactive Programming的新手。我的问题是通过rest API为数据库创建导出功能。 用户点击GET请求 - >服务器读取数据并将数据作为zip文件返回。因为zip文件很大,所以我需要流式传输这些数据。 我的代码如下:
@GetMapping(
value = "/export",
produces = ["application/octet-stream"],
headers = [
"Content-Disposition: attachment; filename=\"result.zip\"",
"Content-Type: application/zip"])
fun streamData(): Flux<Resource> = service.export()
我使用curl如下:
curl http://localhost/export -H "Accept: application/octet-stream"
但它总是返回406 Not Acceptable。 有人帮忙吗?
非常感谢
答案 0 :(得分:0)
headers
注释的@GetMapping
属性不是应写入HTTP响应的标头,而是映射标头。这意味着您的@GetMapping
注释要求HTTP请求包含您列出的标头。这就是请求实际上没有映射到控制器处理程序的原因。
现在您的处理程序返回类型看起来不正确 - Flux<Resource>
表示您打算返回0..*
Resource
个实例并且应该序列化它们。在这种情况下,像ResponseEntity<Resource>
这样的返回类型可能是更好的选择,因为您可以在ResponseEntity
上设置响应标头并将其正文设置为Resource
。
答案 1 :(得分:0)
是吗,伙计?在使用blockLast时,我仍觉得在最后一行使用此解决方案并不好。
@GetMapping("/vehicle/gpsevent", produces = ["application/octet-stream"])
fun streamToZip(): ResponseEntity<FileSystemResource> {
val zipFile = FileSystemResource("result.zip")
val out = ZipOutputStream(FileOutputStream(zipFile.file))
return ResponseEntity
.ok().cacheControl(CacheControl.noCache())
.header("Content-Type", "application/octet-stream")
.header("Content-Disposition", "attachment; filename=result.zip")
.body(ieService.export()
.doOnNext { print(it.key.vehicleId) }
.doOnNext { it -> out.putNextEntry(ZipEntry(it.key.vehicleId.toString() + ".json")) }
.doOnNext { out.write(it.toJsonString().toByteArray(charset("UTF-8"))) }
.doOnNext { out.flush() }
.doOnNext { out.closeEntry() }
.map { zipFile }
.doOnComplete { out.close() }
.log()
.blockLast()
)
}