网站首页/ 信息中心/ 档案百科/

从零构建诊所数字档案馆:SpringBoot+MinIO实战指南

发布时间:2026年08月22日 06:20:24 浏览量:0

一、系统架构与核心技术选型

本系统采用前后端分离架构,后端使用SpringBoot 2.7.18,前端使用Vue 3.3.4。文件存储采用MinIO 8.5.7作为对象存储服务,数据库使用MySQL 8.0.33。这种组合能确保系统稳定、易于扩展,且完全免费开源。

1.1 环境准备清单

在开始前,请确保已安装以下软件:

二、MinIO对象存储服务部署

2.1 MinIO安装与配置

下载并安装MinIO Server:

``` Linux/macOS wget https://dl.min.io/server/minio/release/linux-amd64/minio chmod +x minio ./minio server /data/minio --console-address ":9001" Windows 从 https://min.io/download/windows 下载minio.exe 在命令行执行: minio.exe server D:\minio-data --console-address ":9001" ```

创建MinIO访问密钥:

``` 登录MinIO控制台(http://localhost:9001) 创建新用户:clinic-archive 生成Access Key和Secret Key 记录下这两组密钥,后续配置需要 ```

2.2 创建存储桶

在MinIO控制台中执行:

三、后端服务搭建

3.1 项目初始化

使用Spring Initializr创建项目:

``` 访问 https://start.spring.io/ 选择以下依赖: - Spring Web - Spring Data JPA - MySQL Driver - Lombok 生成并下载项目 ```

解压后,在pom.xml中添加MinIO依赖:

``` io.minio minio 8.5.7 ```

3.2 数据库配置

创建MySQL数据库:

``` CREATE DATABASE clinic_archive_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ```

在application.yml中配置数据库连接:

``` spring: datasource: url: jdbc:mysql://localhost:3306/clinic_archive_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: update show-sql: true properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect format_sql: true ```

3.3 MinIO配置类

创建MinioConfig.java:

``` 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; @Bean public MinioClient minioClient() { return MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); } } ```

在application.yml中添加MinIO配置:

``` minio: endpoint: http://localhost:9000 accessKey: your_access_key secretKey: your_secret_key bucket: clinic-archive-bucket ```

3.4 实体类设计

创建病历档案实体类MedicalRecord.java:

``` @Entity @Table(name = "medical_records") @Data public class MedicalRecord { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private String patientId; @Column(nullable = false) private String patientName; private String diagnosis; @Column(nullable = false) private String fileName; @Column(nullable = false) private String filePath; private String fileType; private Long fileSize; @Column(nullable = false) private LocalDateTime uploadTime; @Column(nullable = false) private String uploadUser; } ```

3.5 文件上传服务实现

从零构建诊所数字档案馆:SpringBoot+MinIO实战指南

创建FileStorageService.java:

``` @Service public class FileStorageService { @Autowired private MinioClient minioClient; @Value("${minio.bucket}") private String bucketName; public String uploadFile(MultipartFile file, String patientId) { try { // 生成唯一文件名 String originalFilename = file.getOriginalFilename(); String fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".")); String fileName = patientId + "_" + System.currentTimeMillis() + fileExtension; // 上传到MinIO minioClient.putObject( PutObjectArgs.builder() .bucket(bucketName) .object(fileName) .stream(file.getInputStream(), file.getSize(), -1) .contentType(file.getContentType()) .build() ); return fileName; } catch (Exception e) { throw new RuntimeException("文件上传失败", e); } } public byte[] downloadFile(String fileName) { try { InputStream stream = minioClient.getObject( GetObjectArgs.builder() .bucket(bucketName) .object(fileName) .build() ); return stream.readAllBytes(); } catch (Exception e) { throw new RuntimeException("文件下载失败", e); } } } ```

3.6 控制器实现

创建ArchiveController.java:

``` @RestController @RequestMapping("/api/archive") @CrossOrigin public class ArchiveController { @Autowired private FileStorageService fileStorageService; @Autowired private MedicalRecordRepository recordRepository; @PostMapping("/upload") public ResponseEntity uploadFile( @RequestParam("file") MultipartFile file, @RequestParam("patientId") String patientId, @RequestParam("patientName") String patientName, @RequestParam("diagnosis") String diagnosis, @RequestParam("uploadUser") String uploadUser) { try { // 上传文件 String fileName = fileStorageService.uploadFile(file, patientId); // 保存记录到数据库 MedicalRecord record = new MedicalRecord(); record.setPatientId(patientId); record.setPatientName(patientName); record.setDiagnosis(diagnosis); record.setFileName(fileName); record.setFilePath("/" + fileName); record.setFileType(file.getContentType()); record.setFileSize(file.getSize()); record.setUploadTime(LocalDateTime.now()); record.setUploadUser(uploadUser); recordRepository.save(record); return ResponseEntity.ok("文件上传成功"); } catch (Exception e) { return ResponseEntity.status(500).body("上传失败: " + e.getMessage()); } } @GetMapping("/download/{fileName}") public ResponseEntity downloadFile(@PathVariable String fileName) { byte[] data = fileStorageService.downloadFile(fileName); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentDispositionFormData("attachment", fileName); return new ResponseEntity<>(data, headers, HttpStatus.OK); } @GetMapping("/records") public ResponseEntity> getRecords( @RequestParam(required = false) String patientId) { List records; if (patientId != null && !patientId.isEmpty()) { records = recordRepository.findByPatientId(patientId); } else { records = recordRepository.findAll(); } return ResponseEntity.ok(records); } } ```

四、前端界面开发

4.1 Vue项目初始化

创建Vue项目:

``` npm create vue@latest clinic-archive-frontend 选择以下配置: - TypeScript: No - JSX: No - Router: Yes - Pinia: Yes - ESLint: Yes - Prettier: Yes cd clinic-archive-frontend npm install npm install axios element-plus ```

4.2 文件上传组件

创建UploadComponent.vue:

``` ```

4.3 档案查询组件

创建SearchComponent.vue:

``` ```

五、系统部署与测试

5.1 后端服务启动

在后端项目根目录执行:

``` ./mvnw spring-boot:run 或 mvn spring-boot:run ```

服务启动后,访问 http://localhost:8080/swagger-ui.html 查看API文档。

5.2 前端服务启动

在前端项目根目录执行:

``` npm run dev ```

服务启动后,访问 http://localhost:5173 使用系统。

5.3 系统测试步骤

  • 步骤1:打开前端页面,填写患者信息
  • 步骤2:选择病历文件(支持PDF、图片、Word)
  • 步骤3:点击上传,观察控制台返回结果
  • 步骤4:在查询页面输入患者ID,验证文件列表显示
  • 步骤5:点击下载按钮,验证文件能正常下载
  • 步骤6:登录MinIO控制台,验证文件已存储到对应桶中

六、生产环境部署建议

6.1 安全加固

修改application.yml,添加JWT认证:

``` spring: security: user: name: admin password: ${ARCHIVE_ADMIN_PASSWORD:ChangeMe123} ```

6.2 数据库备份配置

创建备份脚本backup.sh:

``` !/bin/bash BACKUP_DIR="/backup/clinic-archive" DATE=$(date +%Y%m%d_%H%M%S) mysqldump -u root -p'your_password' clinic_archive_db > $BACKUP_DIR/backup_$DATE.sql 保留最近7天备份 find $BACKUP_DIR -name ".sql" -mtime +7 -delete ```

6.3 MinIO高可用配置

修改MinIO启动命令,使用分布式模式:

``` export MINIO_ROOT_USER=admin export MINIO_ROOT_PASSWORD=ChangeMe123 ./minio server http://node{1...4}/data/minio ```

以上配置完成后,诊所数字档案馆系统即可投入生产使用。系统具备完整的文件上传、存储、查询、下载功能,所有组件均为开源软件,无需支付任何许可费用。

档案制度建设少走弯路 实战教育手把手带你全流程落地
档案制度建设少走弯路 实战教育手把手带你全流程落地
家人们谁懂啊,我去年帮3个小微企业搭档案制度的时候,踩的坑能绕公司前台的奶茶堆三圈。那时候我还是个抱着《档案管理学》啃的理论党,总觉得不就是归个纸嘛有啥难的,直到把公司攒了5年的合同翻得乱七八糟找不到...
2026年08月22日 06:20:24
档案整理规范服务收费标准,这钱花得明白不肉疼
档案整理规范服务收费标准,这钱花得明白不肉疼
哎,哥们儿姐们儿,今儿咱不聊虚的,就唠唠“档案整理规范服务收费标准”这档子事儿。你别一听“规范”、“标准”就头大,觉得又是啥高深莫测、价格云里雾里的服务。我跟你讲,这玩意儿就跟咱家里大扫除一个理儿,只...
2026年08月22日 06:20:24
水利普查档案数字化全流程指南:合规归档+效率提升实操方案
水利普查档案数字化全流程指南:合规归档+效率提升实操方案
不少水利系统的朋友最近都在问,存量水利普查档案转数字化怎么才能符合归档要求,还能少踩坑?毕竟很多单位攒了十几年的普查档案,既有纸质的河湖勘测表、工程台账,也有老的光盘存储数据,整理起来头都大。这篇我就...
2026年08月22日 06:20:24
微信咨询
电话联系
QQ客服
微信咨询一对一服务
服务热线: 028-8744 4417
QQ客服: 2305721818