【问题标题】:Cannot read Part's content (Flux<DataBuffer>) into a single String无法将 Part 的内容 (Flux<DataBuffer>) 读入单个字符串
【发布时间】:2021-05-18 16:07:49
【问题描述】:

在下面的 sn-p 中,我尝试使用 Spring 的 Part 对象提取文件的内容(发送到给定的服务)并将其转换为字符串。

问题是它跳过了映射器函数,并且映射器函数内的代码不会像 filePartMono 的内容为空一样执行,但是当我在运行时检查对象时,它的存储字段具有文件的数据。

public void parseFilePart(Part filePartMono) {
    filePartMono.content().map(dataBuffer -> {
            byte[] bytes = new byte[dataBuffer.readableByteCount()];
            dataBuffer.read(bytes);
            DataBufferUtils.release(dataBuffer);
            String fileContent = new String(bytes, StandardCharsets.UTF_8);
        });
}

【问题讨论】:

  • 为什么函数无效?什么在调用这个函数。你不应该有 void 函数,你需要返回一些东西以便调用代码可以链接。请贴出调用此函数的代码。
  • 该方法应该返回一些 Mono,但即使使用该返回类型,它的行为也是相同的。 void 仅用于测试目的。

标签: java spring spring-webflux


【解决方案1】:

org.springframework.http.codec.multipart.Part.content() 返回Flux&lt;DataBuffer&gt;,这意味着在您订阅此Publisher 之前不会发生任何事情。

如果您的代码可以以阻塞方式执行而不会导致错误,您可以这样重构它以获得 String 结果:

public void parseFilePart(Part filePartMono) {
  List<String> parts = 
    filePartMono.content()
    .map(dataBuffer -> {
          byte[] bytes = new byte[dataBuffer.readableByteCount()];
          dataBuffer.read(bytes);
          DataBufferUtils.release(dataBuffer);
          return new String(bytes, StandardCharsets.UTF_8);
    })
    .collectList()
    .block();
  //do what you want here with the Strings you retrieved
}

如果您确定Flux&lt;DataBuffer&gt; 将始终发出1 个DataBuffer,您可以将.collectList().block() 替换为.blockFirst() 并获得String 结果而不是List&lt;String&gt;

如果你的代码不能以阻塞方式执行,那么你可以这样重构它:

public void parseFilePart(Part filePartMono) {
    filePartMono.content()
    .map(dataBuffer -> {
          byte[] bytes = new byte[dataBuffer.readableByteCount()];
          dataBuffer.read(bytes);
          DataBufferUtils.release(dataBuffer);
          return new String(bytes, StandardCharsets.UTF_8);
    })
    .subscribe(resultString -> {
      //do what you want with the result String here
    });
}

附注我没有测试您的实现以将DataBuffer 转换为String,因此您现在可能需要仔细检查它是否已被实际调用

【讨论】:

  • 你的建议抛出:java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, thread reactor-http-nio-7 不支持
  • 那你不能在那个线程上执行阻塞代码,我将把答案重构为完全反应式。
  • 还是不行。它也跳过了消费者的代码块并立即退出该方法
  • 来源似乎是空的,但事实并非如此。此解决方案有效 manhtai.github.io/posts/flux-databuffer-to-inputstream 。但我想了解我的问题...
猜你喜欢
  • 2021-12-02
  • 2019-12-25
  • 1970-01-01
  • 2018-03-09
  • 2011-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-05
相关资源
最近更新 更多