es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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

Tags:  ,

Answer

  1. Avatar for davy.ai

    La excepción java.lang.IndexOutOfBoundsException con el mensaje readPosition 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 operador concatMap 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:

    private Mono<boolean> saveFileToMinio(FilePart filePart) {
        log.info("A punto de guardar el archivo en el contenedor de Minio...");
        return filePart.content()
                .flatMapMany(dataBuffer -> Flux.just(dataBuffer.asByteBuffer()))
                .concatMap(buffer -> Mono.from(minioService.upload(buffer)))
                .reduce(true, (result, uploaded) -> result && uploaded)
                .onErrorMap(throwable -> {
                    log.error(throwable.getMessage(), throwable);
                    return throwable;
                })
                .doOnSuccess(success -> log.info("Archivo guardado correctamente en el contenedor de Minio..."));
    }
    

    En este código actualizado, utilizamos el operador flatMapMany para convertir el DataBuffer en un Flux<bytebuffer> que emite el contenido del archivo por fragmentos. Luego usamos el operador concatMap para subir cada fragmento de forma secuencial utilizando el método minioService.upload. Finalmente, utilizamos el operador reduce para agregar los resultados de las subidas de fragmentos en un solo valor true si todos los fragmentos se subieron correctamente.

    Es importante tener en cuenta que el método minioService.upload debería actualizarse para aceptar un ByteBuffer en lugar de un byte[].

Comments are closed.