如何在webflux中获取Filepart的大小

时间:2018-07-12 07:16:27

标签: spring-boot spring-webflux

无法弄清楚如何在REST端点中使用FilePart获取文件的实际大小:

@RestController
public class SomeController {

    @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Mono<Long> fileSize(Mono<FilePart> filePart) {

        //How to get size of FilePart?

        // I'm not plan to create a File saving content of FilePart. 
        // Maybe it's possible somehow calculate size of all bytes.

        return Mono.empty();
    }

}

3 个答案:

答案 0 :(得分:2)

当您将文件作为多部分表单数据上传时,会自动创建一个名为“ Content-Length”的请求标头,该标头是在发送请求时计算的。

但是请注意,多部分内容长度略大于文件大小,这是由于创建了一些元数据,例如文件名,边界等。而且,无法,您无法估算此元数据的长度。解释是here

因此,您可以通过以下方式获得尺寸(略有增加):

@RestController
public class SomeController {

    @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Mono<Long> fileSize(Mono<FilePart> filePart, @RequestHeader("Content-Length") long contentLength) {
        System.out.println("Content length is:" + contentLength + "bytes");
        return Mono.empty();
    }

}

答案 1 :(得分:0)

在不先将文件保存到文件或将其缩小为InputStream或类似内容之前,我也无法弄清楚如何获得文件大小。

我最终要做的是向请求添加自定义标头。然后,您可以在控制器中读取标题:

@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Mono<Long> fileSize(Mono<FilePart> filePart, @RequestHeader("File-Size") Long fileSize) {

如果将新参数的类型更改为Map<String, String>MultiValueMap<String, String>HttpHeaders,则将获得所有标头,而不仅仅是自定义标头。

如果您无法更改客户端的请求标头,并且不需要绝对精确的文件大小,则可以使用默认标头Content-Length,该标头无论如何都已经发送了,但这将是几个字节。

答案 2 :(得分:0)

您可以使用Flux<DataBuffer>访问文件部分中的filePart.content()。使用这个。

filePart.content() // for one file, is a Flux with one element
    .map(dataBuffer -> {
         byte[] bytes = new byte[dataBuffer.readableByteCount()]; // <---- here you count the bytes you have. 
         dataBuffer.read(bytes);
         DataBufferUtils.release(dataBuffer);
         String content = new String(bytes, StandardCharsets.UTF_8);
         if (log.isTraceEnabled()) log.trace("File name: {}, content: {}", filePart.filename(),
             content.length() > CONTENT_LENGTH_LIMIT ? content.substring(0, CONTENT_LENGTH_LIMIT) + "..." : content);
         return content;
    })