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

如何将WebFlux WebClient DataBuffer下载与更多操作结合起来

吕嘉荣
2023-03-14

我正在尝试根据先前Web请求的结果下载一个文件(或多个文件)。下载文件后,我需要将之前的Mono结果(hossierandobj)和文件发送到另一个系统。到目前为止,我一直在使用平面地图和Monos。但是当读取大文件时,我无法在文件下载期间使用Mono,因为缓冲区太小。

简化后的代码如下所示:

var filePath = Paths.get("test.pdf");
this.dmsService.search()
    .flatMap(result -> {
        var dossier = result.getObjects().get(0).getProperties();
        var objectId = dossier.getReferencedObjectId();
        return Mono.zip(this.dmsService.getById(objectId), Mono.just(dossier));
    })
    .flatMap(tuple -> {
        var obj = tuple.getT1();
        var dossier = tuple.getT2();

        var media = this.dmsService.getDocument(objectId);
        var writeMono = DataBufferUtils.write(media, filePath);
        return Mono.zip(Mono.just(obj), Mono.just(dossier), writeMono);
    })
    .flatMap(tuple -> {
        var obj = tuple.getT1();
        var dossier = tuple.getT2();
        var objectId = dossier.getReferencedObjectId();
    
        var zip = zipService.createZip(objectId, obj, dossier);
        return zipService.uploadZip(Flux.just(zip));
    })
    .flatMap(newWorkItemId -> {
        return updateMetadata(newWorkItemId);
    })
    .subscribe(() -> {
        finishItem();
    });

DMS服务。search(),此。DMS服务。getById(objectId)zipService。uploadZip()all返回特定类型的Mono<代码>DMS服务。getDocument(objectId)返回由于支持大文件而产生的流量。如果我简单地使用一个文件,使用DataBuffer Mono可以处理小文件。复制:

    ...
    var contentMono = this.dmsService.getDocument(objectId);
    return contentMono;
})
.flatMap(content -> {
    Files.copy(content.asInputStream(), Path.of("test.pdf"));
    ...
}

我尝试过不同的方法,但总是遇到问题。

基于https://www.amitph.com/spring-webclient-large-file-download/#Downloading_a_Large_File_with_WebClient

DataBufferUtils.write(dataBuffer, destination).share().block();

当我尝试此操作时,. block()之后的任何内容都不会执行。没有下载。

如果没有. share(),我得到一个异常,我可能不会使用block:java.lang.IllegalStateException: block()/block First()/block Last()是阻塞的,线程reactor-超文本传输协议-nio-5不支持

由于数据缓冲区。write返回一个Mono。我的下一个假设是,我可以不调用block,而是调用Mono。zip()这与我的其他值一起,但这也从未返回。

var media = this.dmsService.getDocument(objectId);
var writeMono = DataBufferUtils.write(media, filePath);
return Mono.zip(Mono.just(obj), Mono.just(dossier), writeMono);

对于如何实现这一点的任何投入都非常感谢。

共有1个答案

宗政权
2023-03-14

我终于明白了,如果我使用一个可由techannel写的,返回一个通量

var media = this.dmsService.getDocument(objectId);
var file = Files.createTempFile(objectId, ".tmp");
WritableByteChannel filechannel = Files.newByteChannel(file, StandardOpenOption.WRITE);
var writeMono = DataBufferUtils.write(media, filechannel)
    .map(DataBufferUtils::release)
    .then(Mono.just(file));
return Mono.zip(Mono.just(obj), Mono.just(dossier), writeMono);
 类似资料:
  • 我想在React项目的后端合并一个使用语音识别的Python文件。 这里我有一段使用语音识别的Python代码: 我尝试在react组件中导入文件,如下所示: 在这里,我尝试将我的按钮链接到Python文件中的函数: 我收到了它未能编译的消息以及以下内容: 我能做些什么来使这个工作?

  • 我不明白如何结合三个相互依赖的操作。 我有新用户需要保存到基地: > 从基础获取项目。 将第一次操作的数据保存到数据库中 保存到基本的新用户角色 最后,方法返回 到控制器。

  • 我使用https://doc.akka.io/docs/alpakka-kafka/current/consumer.html从kafka使用数据,如下所示: 接下来,我将通过akka http websocket客户端将收到的结果转发到webserver 以下是如何构建websocket客户端: 我有两个问题: > 如何将消费者和websocket客户端组合成一个流,并让它将消息发送到Web服务

  • 为了能够轻松地测试我的SOAP客户机(通过利用MockWebServiceServer),我想使用Spring的WebServiceTemplate。 SOAPendpoint是.NET服务器。基于wsdl,我能够生成bean(主要是请求类)和endpoint接口。 生成的界面如下: SOAPFaultClientException:反序列化操作“CallCheckXML”的请求消息正文时出错。O

  • 问题内容: 我已经使用Python asyncio和aiohttp成功构建了一个RESTful微服务,该服务可侦听POST事件以收集来自各种供料器的实时事件。 然后,它构建一个内存结构,以将事件的最后24小时缓存在嵌套的defaultdict / deque结构中。 现在,我想定期检查该结构到磁盘的位置,最好使用pickle。 由于内存结构可以大于100MB,因此我希望避免在检查点结构所需的时间上