本指南将构建一个具备文件上传、安全存储、元数据管理及在线预览功能的电子公文管理系统。为了确保零门槛落地且具备企业级扩展性,我们采用以下技术栈:
在开始编码前,需先准备好基础存储和数据库服务。我们使用Docker快速部署MySQL、MinIO和kkFileView。请确保你的服务器已安装Docker和Docker Compose。
执行以下命令创建MySQL容器,设置root密码为123456,并创建名为edoc_system的数据库:
MinIO用于存储实际的公文文件。执行以下命令启动MinIO,控制台端口为9001,API端口为9000:
启动后,访问 http://localhost:9001 登录MinIO控制台,手动创建一个名为 official-docs 的Bucket(存储桶),并将访问权限设置为Public或Read。
执行以下命令启动kkFileView,该服务将监听8012端口:
我们需要一张表来记录公文的元数据。请在MySQL的edoc_system数据库中执行以下SQL:
创建一个Spring Boot项目,修改pom.xml,引入必要的依赖。请确保版本号兼容。
在src/main/resources/application.yml中配置数据库连接、MinIO连接信息及预览服务地址:

以下代码包含配置类、实体类、Mapper层、Service层和Controller层,复制即可运行。
该类用于初始化MinIO客户端实例。
```java package com.edoc.config; import io.minio.MinioClient; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Data @Configuration @ConfigurationProperties(prefix = "minio") public class MinioConfig { private String endpoint; private String accessKey; private String secretKey; private String bucketName; @Bean public MinioClient minioClient() { return MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); } } ```包含上传文件和获取预览URL的逻辑。注意:上传文件时会生成唯一的UUID作为文件名存储到MinIO,防止文件名冲突。
```java package com.edoc.service; import com.edoc.config.MinioConfig; import com.edoc.entity.DocInfo; import com.edoc.mapper.DocInfoMapper; import io.minio.MinioClient; import io.minio.PutObjectArgs; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import java.io.InputStream; import java.time.LocalDateTime; @Service public class DocService { @Autowired private MinioClient minioClient; @Autowired private MinioConfig minioConfig; @Autowired private DocInfoMapper docInfoMapper; @Value("${preview.baseUrl}") private String previewBaseUrl; / 上传公文并保存元数据 / public String uploadDoc(MultipartFile file, String docTitle, String uploader) throws Exception { String originalFilename = file.getOriginalFilename(); String suffix = FileUtil.getSuffix(originalFilename); // 生成新的存储文件名 String objectName = IdUtil.simpleUUID() + "." + suffix; // 上传到MinIO try (InputStream inputStream = file.getInputStream()) { minioClient.putObject( PutObjectArgs.builder() .bucket(minioConfig.getBucketName()) .object(objectName) .stream(inputStream, file.getSize(), -1) .contentType(file.getContentType()) .build() ); } // 保存元数据到数据库 DocInfo docInfo = new DocInfo(); docInfo.setDocTitle(docTitle); docInfo.setOriginalName(originalFilename); docInfo.setFileType(suffix); docInfo.setFileSize(file.getSize()); docInfo.setObjectName(objectName); // 拼接完整的文件访问URL,供kkFileView下载使用 String fileUrl = minioConfig.getEndpoint() + "/" + minioConfig.getBucketName() + "/" + objectName; docInfo.setUploader(uploader); docInfo.setCreateTime(LocalDateTime.now()); docInfoMapper.insert(docInfo); return "上传成功,文件ID: " + docInfo.getId(); } / 获取预览URL / public String getPreviewUrl(Long docId) { DocInfo docInfo = docInfoMapper.selectById(docId); if (docInfo == null) { throw new RuntimeException("文档不存在"); } // 构造MinIO文件完整下载地址 String fileUrl = minioConfig.getEndpoint() + "/" + minioConfig.getBucketName() + "/" + docInfo.getObjectName(); // kkFileView通过url参数接收文件地址 return previewBaseUrl + "?url=" + StrUtil.utf8UrlEncode(fileUrl); } } ```项目启动后,我们使用curl命令模拟文件上传和预览请求。准备一个名为test.pdf的测试文件放在当前目录下。
执行以下命令上传文件,公文标题设为“2023年度技术报告”:
```bash curl -F "file=@test.pdf" \ -F "docTitle=2023年度技术报告" \ -F "uploader=ZhangSan" \ http://localhost:8080/api/doc/upload ``>成功返回示例:上传成功,文件ID: 1。请记住返回的ID(假设为1)。
使用上一步获取的ID访问预览接口:
```bash curl http://localhost:8080/api/doc_preview/1 ``>命令行会返回一长串URL,例如:
http://localhost:8012/onlinePreview?url=http%3A%2F%2Flocalhost%3A9000%2Fofficial-docs%2Fa1b2c3d4.pdf
直接复制该URL到浏览器中访问。 如果一切配置正确,你将看到kkFileView的加载界面,随后显示PDF文件的内容,支持翻页、缩放等操作。
docker logs minio-edoc查看日志,确认application.yml中的端口配置与Docker映射一致。http://localhost:9000或局域网IP,不要配置为127.0.0.1,因为Docker容器内的127.0.0.1指向容器自身而非宿主机。StrUtil.utf8UrlEncode对URL进行编码,确保kkFileView能正确解析中文路径。