Spring Boot + MinIO + KKFile:三步搭建企业级文件预览系统
1. 前言
在文档管理系统里,让用户点开就能看,而不是“先下载、再找软件打开”。下面把 MinIO(对象存储) 和 KKFileView(万能预览) 在 Spring Boot 里一次性打通。
2. 先把Minio跑起来
本地一条命令启动:
minio server /data --console-address ":9001"
浏览器打开 http://localhost:9001,默认账号密码都是 minioadmin。
3. Spring Boot 配置
3.1 加依赖
<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.7</version> <!-- 用最新版更稳 -->
</dependency>
3.2 配置文件
# application.properties
minio.endpoint=http://localhost:9000
minio.access-key=minioadmin
minio.secret-key=minioadmin
minio.bucket-name=files
3.3 写Service
@Service
public class MinioService {@Value("${minio.endpoint}")private String endpoint;@Value("${minio.access-key}")private String accessKey;@Value("${minio.secret-key}")private String secretKey;@Value("${minio.bucket-name}")private String bucketName;private MinioClient client;@PostConstructpublic void init() {client = MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();}/*** 上传文件并返回 objectName*/public String upload(MultipartFile file) throws Exception {String objectName = System.currentTimeMillis() + "-" + file.getOriginalFilename();client.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build());return objectName;}/*** 拿到带签名的临时下载地址*/public String getDownloadUrl(String objectName) throws Exception {return client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(objectName).expiry(1, TimeUnit.HOURS) // 1小时有效期.build());}
}
注解:
- @PostConstruct 让 Bean 一加载就初始化 MinioClient,省得每次现建。
- objectName 使用时间戳 + 原文件名,避免重名冲突。
- getPresignedObjectUrl 返回的 URL 带签名,安全又临时,不用担心直链泄露。
4.KKFileView 一键部署
docker run -d -p 8012:8012 --name kkfileview keking/kkfileview:4.4.0
访问 http://localhost:8012,看到欢迎页就 OK。
5. 把预览地址拼出来
5.1 再加一行配置
kkfileview.server=http://localhost:8012
5.2 Service 里补方法
@Value("${kkfileview.server}")
private String kkServer;/*** 生成 KKFileView 预览地址*/
public String buildPreviewUrl(String objectName) throws Exception {String downloadUrl = getDownloadUrl(objectName);return kkServer + "/onlinePreview?url="+ URLEncoder.encode(downloadUrl, StandardCharsets.UTF_8);
}
注解:
- URLEncoder.encode 保证 URL 作为 Query 参数时不会炸。
- downloadUrl 已经带签名,KK 拿到就能直接拉文件。
- 返回的地址直接丢给前端,iframe 或新窗口打开即可,零代码量嵌入。
6.暴露接口
@RestController
@RequestMapping("/files")
@RequiredArgsConstructor
public class FileController {private final MinioService minioService;/*** 上传接口*/@PostMapping("/upload")public ApiResp<String> upload(@RequestParam MultipartFile file) {try {String objectName = minioService.upload(file);return ApiResp.success(objectName);} catch (Exception e) {return ApiResp.fail(e.getMessage());}}/*** 预览接口*/@GetMapping("/preview")public ApiResp<String> preview(@RequestParam String objectName) {try {String previewUrl = minioService.buildPreviewUrl(objectName);return ApiResp.success(previewUrl);} catch (Exception e) {return ApiResp.fail(e.getMessage());}}
}
注解:
- 统一返回 ApiResp,前端省事。
- try-catch 把异常转成友好提示,不给用户看 500 页面。
- 两个接口都是 RESTful,前端 Vue / React / 小程序都能直接调。
测试
- Postman 调 /files/upload,拿到 objectName。
- 浏览器直接开 /files/preview?objectName=xxx,Word、Excel、PDF 秒开。