Sube archivos grandes Spring Webflux
Quiero subir archivos a un contenedor de archivos de Minio. Los archivos más pequeños funcionan correctamente con este código:
private Mono<boolean> saveFileToMinio(FilePart filePart) {
log.info("A punto de guardar la base de datos en el contenedor de Minio...");
Mono<boolean> result = Mono.from(
filePart.content().flatMap(dataBuffer -> {
var bytes = dataBuffer.asByteBuffer().array();
dataBuffer.read(bytes);
DataBufferUtils.release(dataBuffer);
return Flux.just(bytes);
})
.flatMap(databaseFileService::write)
.then(Mono.just(true))
.onErrorMap(throwable -> {
log.error(throwable.getMessage(), throwable);
return throwable;
}));
log.info("Base de datos guardada correctamente en el contenedor de Minio...");
return result;
}
Necesito proporcionar un byte[]
para que mi servicio de Minio lo pueda subir. Los archivos más pequeños funcionan como se espera (se almacenarán en el contenedor). Pero los archivos más grandes (12 MB en mi prueba) no funcionan.
Obtengo esta excepción:
java.lang.IndexOutOfBoundsException: La posición de lectura 0 y la longitud 1024 deben ser menores que la posición de escritura 808
davy.ai
La excepción
java.lang.IndexOutOfBoundsException
con el mensajereadPosition 0 y length 1024 deberían ser menores que writePosition 808
indica que el búfer utilizado para almacenar los bytes del archivo que se está subiendo no es lo suficientemente grande como para contener todos los datos en una sola operación.Para evitar este problema y subir archivos más grandes al contenedor de archivos de Minio, es necesario leer el archivo por fragmentos y subir cada fragmento por separado. Una forma de lograr esto es utilizando la clase
Flux
para leer el contenido del archivo como una secuencia de fragmentos de datos, y luego utilizar el operadorconcatMap
para subir cada fragmento de forma secuencial.Aquí hay una versión actualizada del método
saveFileToMinio
que lee el contenido del archivo por fragmentos y sube cada fragmento por separado:En este código actualizado, utilizamos el operador
flatMapMany
para convertir elDataBuffer
en unFlux<bytebuffer>
que emite el contenido del archivo por fragmentos. Luego usamos el operadorconcatMap
para subir cada fragmento de forma secuencial utilizando el métodominioService.upload
. Finalmente, utilizamos el operadorreduce
para agregar los resultados de las subidas de fragmentos en un solo valortrue
si todos los fragmentos se subieron correctamente.Es importante tener en cuenta que el método
minioService.upload
debería actualizarse para aceptar unByteBuffer
en lugar de unbyte[]
.