如何在Spring Webflux中获取FilePart的大小

Vik*_* V. 5 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

更新 以下是我进行文件大小和图像分辨率验证的方法。

控制器:

@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ResponseStatus(HttpStatus.CREATED)
public Mono<Void> upload(Mono<FilePart> file) {
    return file.flatMap(filepart -> fileService.upload(filepart));
}
Run Code Online (Sandbox Code Playgroud)

服务层的验证方法:

private Mono<byte[]> validateFileSize(FilePart filePart) {
    var maxSize = 1024;
    return FilePartUtils.getByteArray(filePart)
            .filter(bytes -> bytes.length <= maxSize)
            .switchIfEmpty(Mono.error(() -> new InvalidStateException(MAX_FILE_SIZE_REACHED, Map.of("size", maxSize))));
}

private Mono<Resolution> validateResolution(byte[] fileBytes) {
    // Use image.getWidth and image.getHeight to check resolution against you expectations
    return convertToImage(fileBytes).map(image -> validateResolution(image)); 
}

public Mono<BufferedImage> convertToImage(byte[] byteArray) {
    try {
        // but ImageIO.read is blocking method
        return Mono.just(ImageIO.read(new ByteArrayInputStream(byteArray)));
    } catch (IOException e) {
        return Mono.error(new InvalidStateException(UPLOAD_FILE_ABORTED, Map.of()));
    }
}
Run Code Online (Sandbox Code Playgroud)

Abh*_*rty 5

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

但请注意,由于创建了一些元数据(如文件名、边界等),多部分内容长度略大于文件大小。您无法估计此元数据的长度。解释就在这里

因此,您可以通过以下方式获得大小(稍微增加):

@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();
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 依赖内容长度标头是否安全?例如,恶意用户是否可以将此标头设置为 100kb,而文件却大得多? (5认同)