通过 Spring WebClient 流式上传大文件

Posted

技术标签:

【中文标题】通过 Spring WebClient 流式上传大文件【英文标题】:Stream-uploading large files via Spring WebClient 【发布时间】:2021-03-07 07:09:39 【问题描述】:

我遇到了与此处提到的相同的问题。

Stream upload 'POST' in Spring WebClient

我需要通过 Spring WebClient 上传大文件,并且我不想读取内存中的文件来执行此操作。

我将文件存储在 Minio S3 存储桶中,界面允许我以 java.io.InputStream 的形式接收文件。

然后我想将其作为上传主体流式传输到另一个服务端点。

产生Content type 'application/octet-stream' not supported for bodyType=org.springframework.web.reactive.function.BodyInserters 错误的解决方案是通过以下方式产生的:

public String uploadFile(String fileId, String fileName) 
        InputStream fileInputStream = minioClient.getObject(bucketName, fileId);

        return webClient.post()
                .uri(properties.getUrl())
                .contentType(APPLICATION_OCTET_STREAM)
                .headers(httpHeaders -> 
                    httpHeaders.set(FILE_NAME, fileName);
                )
                .bodyValue(BodyInserters.fromResource(fileInputStream)
                .retrieve()
                .bodyToFlux(String.class)
                .blockFirst();
    

【问题讨论】:

【参考方案1】:

您可以尝试使用DataBufferUtils.readInputStream(..) (javadoc) 创建Flux<DataBuffer>。然后使用适当的BodyInserters.fromDataBuffers(..) (javadoc) 传递给.bodyValue()。这应该不会正确地将整个文件加载到内存中,而是缓冲并逐块发送。

我不确定这是否适用于 application/octet-stream 作为内容类型,因为我无法对其进行测试。

【讨论】:

以上是关于通过 Spring WebClient 流式上传大文件的主要内容,如果未能解决你的问题,请参考以下文章

Spring WebClient:如何将大字节 [] 流式传输到文件?

Spring webclient exchangeToFlux()不发出HTTP请求

Spring WebClient 作为 RestTemplate 的替代品

通过@Bean 提供的 RestTemplateBuilder 流式上传缓冲完整文件

Spring Boot 自动配置的 Jackson ObjectMapper 默认不用于 WebFlux WebClient

golang gin框架中实现大文件的流式上传