当文件的内容(Flux;DataBuffer;)包装在另一个对象中时,无法使用WebClient上载文件 [英] Cannot upload a file using WebClient when its content ( Flux<DataBuffer>) is wrapped in another object

查看:10
本文介绍了当文件的内容(Flux;DataBuffer;)包装在另一个对象中时,无法使用WebClient上载文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Spring Boot:2.5.6,kotlin:1.5.31,kotlinx-coroutines-active:1.5.2

我正在尝试下载一个pdf并立即上传到http://localhost:3000/upload,如下所示:

Class Mediator(val dataBuffer: Flux<DataBuffer>, val url: String)

runBlocking {
  getMediator()
    .flatMap { uploadFile(it) }
    .subscribe()
}

  private fun getMediator(): Mono<Mediator> {
    return WebClient.create(
            "https://server.com/assets/file.pdf")
        .get()
        .exchangeToMono { response ->
          Mono.just(
              Mediator(response.bodyToFlux(DataBuffer::class.java), "http://localhost:3000/upload"))
        }
  }
  private fun uploadFile(mediator: Mediator): Mono<ResponseEntity<Void>> {
    return WebClient.create(mediator.url)
        .put()
        .contentType(MediaType.APPLICATION_OCTET_STREAM)
        .body(mediator.dataBuffer)
        .retrieve()
        .toBodilessEntity()
  }

当我运行这段代码时,我可以看到我的服务器收到一个调用并创建了一个空文件(大小为0)。不会引发任何错误。我无法解释为什么这段代码不能将字节传输到我的上载端点。在测试过程中,我意识到问题可能出在getMediator返回的Mediator对象中。不知何故,uploadFile中的body不像包装的Flux<DataBuffer>

推荐答案

我找到了一种方法。只是回答我自己的问题,以防这可能会对其他人有所帮助。

data class Mediator(val data: Flux<DataBuffer>, val url: String)
data class UploadUrl(val url: String)

runBlocking {
  getFileDataBuffer(url)
     .flatMap { prepareUpload(it.headers.contentLength, it.body) }
     .flatMap { uploadFile(it.url, it.dataBuffer!!)}
}.subscribe()

private fun getFileDataBuffer(url:String): Mono<ResponseEntity<Flux<DataBuffer>>> {
  return WebClient.create(url).get().retrieve().toEntityFlux()
}

private fun prepareUpload(length: Long, data: Flux<DataBuffer>?): Mono<Mediator> {
    return WebClient.create("http://localhost:3000/prepare")
        .post()
        .contentType(MediaType.APPLICATION_JSON)
        .bodyValue("""{"size":${length}}""")
        .exchangeToMono { res ->
          res.bodyToMono(String::class.java).map { parseJson<UploadUrl>(it) }.map {
            Mediator(data, it.url)
          }
        }
  }

private fun uploadFile(url: String, data: Flux<DataBuffer>): Mono<ResponseEntity<Void>> {
    return WebClient.create(url)
        .put()
        .contentType(MediaType.APPLICATION_OCTET_STREAM)
        .body(data)
        .retrieve()
        .toBodilessEntity()
  }

这篇关于当文件的内容(Flux;DataBuffer;)包装在另一个对象中时,无法使用WebClient上载文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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