Backend Development 10 min read

Deploying kkfileviewer with Docker and Integrating MinIO in a Spring Boot Application

This guide walks through installing kkfileviewer in a Docker container, building and running the image, then shows how to add MinIO support to a Spring Boot project with Maven dependencies, configuration classes, utility methods, and REST endpoints for file upload and preview.

Top Architect
Top Architect
Top Architect
Deploying kkfileviewer with Docker and Integrating MinIO in a Spring Boot Application

In this tutorial, a top‑level architect demonstrates how to set up the open‑source file preview service kkfileviewer using Docker, and then integrate MinIO object storage into a Spring Boot application for uploading and previewing files.

1. Container installation of kkfileviewer

1.1 Download files

Use the kkfileviewer 4.4.0‑beta source repository:

https://codeup.aliyun.com/6254dee9a923b68581caaf50/kkfileviewer.git

1.2 Build the Docker image

git clone https://codeup.aliyun.com/6254dee9a923b68581caaf50/kkfileviewer.git
cd kkfileviewer
docker build -t kkfileview:v4.4.0 .

1.3 Run kkfileviewer

docker run -d -p 8012:8012 --name kkfileview kkfileview:v4.4.0

1.4 Test access

Open http://<your‑ip>:8012 in a browser to verify the service is running.

2. Spring Boot integration with MinIO

2.1 Add Maven dependency

<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.5.11</version>
</dependency>

2.2 Configuration (application.yml / application.properties)

# MinIO file storage configuration
minio:
  endpoint: http://xxxxx:9000
  accessKey: xxxx
  secretKey: xxxxx
  bucketName: test

2.3 MinIO configuration class

package com.sunny.config;

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 MinioConfig {
    @Value("${minio.endpoint}")
    private String endPoint;
    @Value("${minio.accessKey}")
    private String accessKey;
    @Value("${minio.secretKey}")
    private String secretKey;
    @Value("${minio.bucketName}")
    private String bucketName;

    @Bean
    protected MinioClient minioClient() {
        return MinioClient.builder()
                .endpoint(endPoint)
                .credentials(accessKey, secretKey)
                .build();
    }
}

2.4 MinIO utility class

package com.sunny.utils;

import com.sunny.entity.common.ApiResult;
import com.sunny.exception.AppException;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.http.Method;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;

@Component
public class MinioUtils {
    @Value("${minio.bucketName}")
    private String bucketName;
    @Resource
    private MinioClient minioClient;

    public ApiResult uploadFile(MultipartFile file) throws AppException {
        String fileName = System.currentTimeMillis() + file.getOriginalFilename();
        try (InputStream fi = file.getInputStream()) {
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .contentType(file.getContentType())
                    .object(fileName)
                    .stream(fi, fi.available(), -1)
                    .build();
            minioClient.putObject(putObjectArgs);
        } catch (Exception e) {
            throw new AppException("文件上传失败" + e.getMessage());
        }
        return ApiResult.ok(fileName);
    }

    public ApiResult getPreviewUrl(String objectName) throws AppException {
        try {
            GetPresignedObjectUrlArgs urlArgs = GetPresignedObjectUrlArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .method(Method.GET)
                    .build();
            return ApiResult.ok(minioClient.getPresignedObjectUrl(urlArgs));
        } catch (Exception e) {
            throw new AppException("获取预览链接失败" + e.getMessage());
        }
    }
}

2.5 REST controller

package com.sunny.controller;

import com.sunny.entity.common.ApiResult;
import com.sunny.exception.AppException;
import com.sunny.utils.MinioUtils;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequestMapping("/file")
public class FileOperationController {
    @Resource
    private MinioUtils minioUtils;

    @PostMapping("/upload")
    public ApiResult upload(MultipartFile file) throws AppException {
        return minioUtils.uploadFile(file);
    }

    @GetMapping("/getPreviewUrl")
    public ApiResult getPreviewUrl(String fileName) throws AppException {
        return minioUtils.getPreviewUrl(fileName);
    }
}

3. Testing the integration

3.1 Upload a file

Use the /file/upload endpoint to send a multipart file; the response returns the generated object name stored in MinIO.

3.2 Obtain preview URL

Call /file/getPreviewUrl?fileName=<objectName> to receive a presigned URL; paste this URL into the kkfileviewer UI to view the file.

3.3 File preview

The preview URL is loaded by kkfileviewer, allowing users to view PDFs, images, or other supported formats directly in the browser.

By following these steps, developers can quickly deploy a file preview service and connect it with MinIO storage in a Spring Boot backend, enabling seamless upload and preview functionality for various file types.

Dockerbackend developmentSpring BootkkfileviewerMinIOFile Preview
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.