Spring WebFlux Webclient接收应用程序/八位字节流文件作为Mono [英] Spring WebFlux Webclient receiving an application/octet-stream file as a Mono

查看:868
本文介绍了Spring WebFlux Webclient接收应用程序/八位字节流文件作为Mono的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Kotlin中制作一个小型Spring WebFlux应用程序的原型.该应用程序需要从远程REST端点获取tar存档,并将其本地存储在磁盘上.听起来很简单.

I'm prototyping a small Spring WebFlux application in Kotlin. This application needs to GET a tar archive from a remote REST endpoint and store it locally on disk. Sounds simple.

我首先创建了一个集成测试,该启动测试将使用提供tar存档的模拟REST终结点启动spring服务器和其他WebFlux服务器.

I first created an integration test that starts the spring server and one other WebFlux server with a mock REST endpoint that serves the tar archive.

测试应该如下:

1)应用:获取mock-server/archive

2)模拟服务器:主体中状态为200和tar存档的响应为附件类型

2) mock-server: response with status 200 and tar archive in body as type attachment

3)应用:阻塞直到接收到所有字节,然后解压缩并使用文件

3) app: block until all bytes received, then untar and use files

我遇到的问题是,当我尝试将字节收集到应用程序上的ByteArray中时,它将永远阻塞.

The problem I'm having is that when I try and collect the bytes into a ByteArray on the app, it blocks forever.

我的mock-server/archive路由到以下功能:

fun serveArchive(request: ServerRequest): Mono<ServerResponse> {
    val tarFile = FileSystemResource(ARCHIVE_PATH)
    assert(tarFile.exists() && tarFile.isFile && tarFile.contentLength() != 0L)
    return ServerResponse
            .ok()
            .contentType(MediaType.APPLICATION_OCTET_STREAM)
            .contentLength(tarFile.contentLength())
            .header("Content-Disposition", "attachment; filename=\"$ARCHIVE_FNAME\"")
            .body(fromResource(tarFile))
}

然后我的应用使用以下内容进行调用:

Then my app calls that with the following:

private fun retrieveArchive {
    client.get().uri(ARCHIVE_URL).accept(MediaType.APPLICATION_OCTET_STREAM)
            .exchange()
            .flatMap { response ->
                storeArchive(response.bodyToMono())
            }.subscribe()
}

private fun storeArchive(archive: Mono<ByteArrayResource>): Mono<Void> {
    val archiveContentBytes = archive.block() // <- this blocks forever
    val archiveContents = TarArchiveInputStream(archiveContentBytes.inputStream)
    // read archive
}

我已经看到如何最好地从Spring WebClient的ClientResponse获取字节数组?,这就是为什么我尝试使用ByteArrayResource的原因.

I've see How to best get a byte array from a ClientResponse from Spring WebClient? and that's why I'm trying to use the ByteArrayResource.

当我逐步浏览所有内容时,我发现serveArchive似乎正在运行(assert语句说我正在传递的文件存在并且其中有一些字节).在retrieveArchive中,我得到200,并且可以在.headers中看到所有适当的信息(content-type,content-length看起来都不错).当我进入storeArchive并尝试使用block从Mono中检索字节时,它只会永远阻塞.

When I step through everything, I see that serveArchive seems to be working (the assert statement says the file I'm passing exists and there are some bytes in it). In retrieveArchive I get a 200 and can see all the appropriate information in the .headers (content-type, content-length all look good). When I get down to storeArchive and try to retrieve the bytes from the Mono using block, it simply blocks forever.

我完全不知道如何调试这样的东西.

I'm at a complete loss of how to debug something like this.

推荐答案

您只需要将转换后的主体从flatMap返回,以便将其从Mono<T>转换为T:

You just have to return the converted body from the flatMap so it transforms from Mono<T> to T:

client.get().uri(ARCHIVE_URL).accept(MediaType.APPLICATION_OCTET_STREAM)
            .exchange()
            .flatMap { response ->
                response.bodyToMono(ByteArrayResource::class.java)
            }
            .map { archiveContentBytes ->
                archiveContentBytes.inputStream
            }
            .doOnSuccess { inputStream ->
                //here is you code to do anything with the inputStream
                val archiveContents = TarArchiveInputStream(inputStream)
            }
            .subscribe()

这篇关于Spring WebFlux Webclient接收应用程序/八位字节流文件作为Mono的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆