Skip to content

Minio

Step1 Add config file.

package org.demo.conf.cxbox.customization.file;

import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MinioFileConfig {

    @Bean
    public MinioClient minioClient(
            @Value("${minio.access.name}") String accessKey,
            @Value("${minio.access.secret}") String accessSecret,
            @Value("${minio.url}") String minioUrl) {
        return MinioClient.builder()
                .endpoint(minioUrl)
                .credentials(accessKey, accessSecret)
                .build();
    }

}

Step2 Add Controller for file storage.

package org.demo.conf.cxbox.customization.file;

import org.cxbox.core.file.controller.AbstractCxboxFileController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import static org.cxbox.core.config.properties.APIProperties.CXBOX_API_PATH_SPEL;

@RestController
@RequestMapping(CXBOX_API_PATH_SPEL + "/file")
public class FileController extends AbstractCxboxFileController {

}
Step3 Add FileService for file storage.
package org.demo.conf.cxbox.customization.file;

import io.minio.*;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.cxbox.core.file.dto.FileDownloadDto;
import org.cxbox.core.file.service.CxboxFileService;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.UUID;

@Service
@RequiredArgsConstructor
public class FileService implements CxboxFileService {

    public static final String FILENAME_FIELD = "filename";
    public static final int FIVE_MIB = 5242880;

    private final MinioClient minioClient;

    @Value("${minio.bucket.name}")
    private final String defaultBucketName;

    @SneakyThrows
    @Override
    public <D extends FileDownloadDto> String upload(@NonNull D file, @Nullable String source) {
        var contentType = file.getType();
        var name = file.getName();
        ObjectWriteResponse objectWriteResponse = minioClient.putObject(PutObjectArgs
                .builder()
                .bucket(defaultBucketName)
                .object(UUID.randomUUID().toString())
                .contentType(contentType)
                .userMetadata(Collections.singletonMap(FILENAME_FIELD, name))
                .stream(file.getContent().get(), -1, FIVE_MIB)
                .build()
        );
        return objectWriteResponse.object();
    }

    @SneakyThrows
    @Override
    public FileDownloadDto download(@NonNull String id, @Nullable String source) {
        StatObjectResponse statObjectResponse = minioClient.statObject(StatObjectArgs
                .builder()
                .bucket(defaultBucketName)
                .object(id)
                .build()
        );
        return new FileDownloadDto(
                () -> getObject(id), statObjectResponse.size(),
                statObjectResponse.userMetadata().get(FILENAME_FIELD),
                statObjectResponse.contentType()
        );
    }

    @SneakyThrows
    private GetObjectResponse getObject(@NotNull String id) {
        return minioClient.getObject(GetObjectArgs
                .builder()
                .bucket(defaultBucketName)
                .object(id)
                .build()
        );
    }

    @SneakyThrows
    @Override
    public void remove(@NonNull String id, @Nullable String source) {
        minioClient.removeObject(RemoveObjectArgs
                .builder()
                .bucket(defaultBucketName)
                .object(id)
                .build()
        );
    }

}

Step1 Add config file.

@Configuration
public class PlatformFileMinioConfig {
    @Bean
    public MinioClient minioClient(
            @Value("${minio.access.name}") String accessKey,
            @Value("${minio.access.secret}") String accessSecret,
            @Value("${minio.url}") String minioUrl) {
        return MinioClient.builder()
                .endpoint(minioUrl)
                .credentials(accessKey, accessSecret)
                .build();
    }    
}

Step2 Add Controller for file storage.

public class PlatformMinioFileController {
public static final String FILENAME_FIELD = "filename";
public static final int FIVE_MIB = 5242880;
private final MinioClient minioClient;
private final String defaultBucketName;

    public PlatformDemoMinioFileController(
            MinioClient minioClient,
            @Value("${minio.bucket.name}") String defaultBucketName
    ) {
        this.minioClient = minioClient;
        this.defaultBucketName = defaultBucketName;
    }

    @SneakyThrows
    @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public PlatformResponseDTO<FileUploadDto> upload(MultipartFile file, String source) {
        String contentType = file.getContentType();
        String name = file.getOriginalFilename();
        ObjectWriteResponse objectWriteResponse = minioClient.putObject(PutObjectArgs
                .builder()
                .bucket(defaultBucketName)
                .object(UUID.randomUUID().toString())
                .contentType(contentType)
                .userMetadata(Collections.singletonMap(FILENAME_FIELD, name))
                .stream(file.getInputStream(), -1, FIVE_MIB)
                .build()
        );
        String id = objectWriteResponse.object();
        return new PlatformResponseDTO<FileUploadDto>()
                .setData(new FileUploadDto(id, name, contentType));
    }

    @SneakyThrows
    @GetMapping
    public ResponseEntity<StreamingResponseBody> download(String id, String source, boolean preview) {
        GetObjectResponse getObjectResponse = minioClient.getObject(GetObjectArgs
                .builder()
                .bucket(defaultBucketName)
                .object(id)
                .build()
        );
        StatObjectResponse statObjectResponse = minioClient.statObject(StatObjectArgs
                .builder()
                .bucket(defaultBucketName)
                .object(id)
                .build()
        );
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=\"" + statObjectResponse.userMetadata().get(FILENAME_FIELD) + "\"")
                .contentLength(statObjectResponse.size()) //
                .body(outputStream -> IOUtils.copy(getObjectResponse, outputStream, FIVE_MIB));
    }

    @SneakyThrows
    @DeleteMapping
    public PlatformResponseDTO<Void> remove(String id, String source) {
        minioClient.removeObject(RemoveObjectArgs
                .builder()
                .bucket(defaultBucketName)
                .object(id)
                .build()
        );
        return new PlatformResponseDTO<>();
    }

}
Step3 Disable platformFileController

public class DisableControllerBFPP implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry) beanFactory;
        beanDefinitionRegistry.removeBeanDefinition("platformFileController");
    }

}