当前位置: 首页 > 知识库问答 >
问题:

Spring WebFlux Webclient接收作为单声道的应用程序/八位组流文件

苏乐童
2023-03-14

我正在Kotlin中构建一个小型Spring WebFlux应用程序的原型。这个应用程序需要从远程RESTendpoint获取一个tar归档文件,并将其存储在本地磁盘上。听起来很简单。

我首先创建了一个集成测试,它启动spring服务器和一个带有模拟RESTendpoint的WebFlux服务器,该endpoint为tar存档提供服务。

测试应该是这样的:

1)app:GETmock-server/archive

2)mock-server:状态为200的响应,正文中的tar存档类型为attachment

我遇到的问题是,当我尝试将字节收集到应用程序上的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
}

我已经看到了如何最好地从Spring WebClient的ClientResponse中获取字节数组?这就是我试图使用ByteArrayResource的原因。

当我遍历所有内容时,我看到servearchive似乎正在工作(assert语句表示我正在传递的文件存在,并且其中有一些字节)。在retrievearchive中,我得到一个200,并且可以在.headers中看到所有适当的信息(内容类型、内容长度看起来都很好)。当我进入storearchive并尝试使用block从单声道中检索字节时,它只是永远阻塞。

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

共有1个答案

宦翔飞
2023-03-14

您只需从flatmap返回转换后的主体,以便它从mono 转换为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()
 类似资料:
  • 我正在为上传文件创建一个简单的。从其他API中,我发现它们使用“”内容类型。但对我来说,“”似乎要简单得多。 如果我不打算在文件中发送更多的表单数据,那么有什么理由使用“”而不是“”呢?

  • 我有一个基于jersey的web服务,它生成一个“多部分/混合”响应,如下所示:该方法读取一个文件,并应以八位字节格式返回它。 我的问题是:如何确保响应为八位字节流类型?我知道我也可以将上述方法注释为: 但是我特别要求在发送八位流格式的文件时将响应内容类型设置为“多部分/混合”。 上面的方法做到了吗?我的假设是有,但我没有具体的理由。 提前谢谢你!

  • 我有一个第三方服务,它用文件向我的Django应用程序发出POST请求。要成功上传到Django应用程序,请求必须具有“多部分/表单数据”内容类型,但在我的案例和请求中,内容类型是“八位流”。文件总是空的。我怎么能在Django中接收八位流内容类型的文件?

  • 我写一个服务器端应用程序与嵌入jetty接收一些请求从第三方客户端。客户端将一些小文件上传到服务器。但是我很惊讶地看到,客户端并没有上传文件数据作为应用程序/八位流,而是上传了一个json作为应用程序/json,其中包括文件的所有元数据,并在一个字段中将所有数据作为字符串 {“_id”:“水果”,“名称”:“水果”,“_shasum”:“4954f1f8b4a8cbf9ea6b675face476

  • 我的REST控制器方法应该返回Mono,它必须由两个并行请求构建到另一个web服务,并处理它们的响应,其中一个请求返回Mono,另一个请求返回Flux 如何将单声道的响应与熔剂的响应结合起来进行处理? 显然,控制器是错误的,因为: 1)接受2个或更多的Mono,其中我有Mono和Flux-如何将它们组合起来? 2)也不确定: 是否正确? 有什么建议吗?

  • 我有一个简单的RabbitMQ源和接收器。我正在将消息发布到具有以下属性的源队列: 和JSON负载: RabbitMQ接收器使用而不是JSON获取消息。 我尝试使用以下属性启动应用程序: 但这于事无补。 流定义: 如何将内容类型设置为应用程序/json?参考指南似乎没有答案。 发布版本: spring-cloud-dataflow-server:2.0.1。释放 spring-cloud-skip