带有WebFlux的响应zip文件

时间:2018-01-24 04:36:43

标签: stream kotlin reactive-programming spring-webflux rx-kotlin

我是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。 有人帮忙吗?

非常感谢

2 个答案:

答案 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()
        )
}