Spring WebFlux Webclient 接收一个 application/octet-stream 文件作为 Mono
Spring WebFlux Webclient receiving an application/octet-stream file as a Mono
我正在使用 Kotlin 制作一个小型 Spring WebFlux 应用程序的原型。此应用程序需要从远程 REST 端点获取 tar 存档并将其存储在本地磁盘上。听起来很简单。
我首先创建了一个集成测试,它 starts spring 服务器和另一个 WebFlux 服务器,该服务器具有为 tar 存档提供服务的模拟 REST 端点。
测试应该是这样的:
1) 应用程序:获取 mock-server/archive
2) 模拟服务器:状态为 200 的响应和 tar 正文中的存档类型为附件
3) 应用程序:阻塞直到接收到所有字节,然后取消tar 并使用文件
我遇到的问题是,当我尝试将字节收集到应用程序的 ByteArray
中时,它会永远阻塞。
我的 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))
}
然后我的应用使用以下内容调用它:
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
}
我看到了 ,这就是我尝试使用 ByteArrayResource
.
的原因
当我逐步执行所有操作时,我看到 serveArchive
似乎在工作(断言语句表明我正在传递的文件存在并且其中有一些字节)。在 retrieveArchive
中我得到一个 200 并且可以在 .headers
中看到所有适当的信息(content-type,content-length 看起来都不错)。当我下降到 storeArchive
并尝试使用 block
从 Mono 检索字节时,它只会永远阻塞。
我完全不知道如何调试这样的东西。
您只需 return 从 flatMap
转换后的正文,以便它从 Mono<T>
转换为 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()
我正在使用 Kotlin 制作一个小型 Spring WebFlux 应用程序的原型。此应用程序需要从远程 REST 端点获取 tar 存档并将其存储在本地磁盘上。听起来很简单。
我首先创建了一个集成测试,它 starts spring 服务器和另一个 WebFlux 服务器,该服务器具有为 tar 存档提供服务的模拟 REST 端点。
测试应该是这样的:
1) 应用程序:获取 mock-server/archive
2) 模拟服务器:状态为 200 的响应和 tar 正文中的存档类型为附件
3) 应用程序:阻塞直到接收到所有字节,然后取消tar 并使用文件
我遇到的问题是,当我尝试将字节收集到应用程序的 ByteArray
中时,它会永远阻塞。
我的 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))
}
然后我的应用使用以下内容调用它:
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
}
我看到了 ByteArrayResource
.
当我逐步执行所有操作时,我看到 serveArchive
似乎在工作(断言语句表明我正在传递的文件存在并且其中有一些字节)。在 retrieveArchive
中我得到一个 200 并且可以在 .headers
中看到所有适当的信息(content-type,content-length 看起来都不错)。当我下降到 storeArchive
并尝试使用 block
从 Mono 检索字节时,它只会永远阻塞。
我完全不知道如何调试这样的东西。
您只需 return 从 flatMap
转换后的正文,以便它从 Mono<T>
转换为 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()