【问题标题】:Response zip file with WebFlux使用 WebFlux 响应 zip 文件
【发布时间】:2018-01-24 04:36:42
【问题描述】:

我是 Spring 5 和响应式编程的新手。我的问题是通过 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。 有人帮忙吗?

非常感谢

【问题讨论】:

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


    【解决方案1】:

    @GetMapping 注解的headers 属性不是应该写入 HTTP 响应的标头,而是映射标头。这意味着您的 @GetMapping 注释要求 HTTP 请求包含您列出的标头。这就是请求实际上没有映射到您的控制器处理程序的原因。

    现在您的处理程序返回类型看起来不正确 - Flux&lt;Resource&gt; 意味着您打算返回 0..* Resource 实例并且它们应该被序列化。在这种情况下,像ResponseEntity&lt;Resource&gt; 这样的返回类型可能是更好的选择,因为您可以在ResponseEntity 上设置响应标头并使用Resource 设置其正文。

    【讨论】:

    • 我明白你的意思。但我的服务返回 Flux。如何将其传输到 JSON 文件并将所有内容放入 result.zip 文件中?谢谢
    【解决方案2】:

    对吗,伙计?在使用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()
            )
    }
    

    【讨论】:

    • 该解决方案将像blockLast()那样缓冲内存中的所有内容@
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-05
    • 1970-01-01
    • 2020-09-18
    • 2020-08-24
    • 1970-01-01
    • 2019-12-11
    相关资源
    最近更新 更多