科技部门数字档案馆系统:从零搭建到文件自动化归档实操指南

一、系统核心架构与选型

本系统采用微服务架构,确保高可用性与可扩展性。核心组件包括:

  • 文件存储层:MinIO对象存储,用于存放非结构化档案文件。
  • 元数据与索引层:PostgreSQL数据库存储档案元数据,Elasticsearch提供全文检索。
  • 业务处理层:基于Spring Boot的Java服务,处理归档、审批、查询等核心逻辑。
  • 前端展示层:Vue.js构建的管理后台。

1.1 基础环境准备

使用Docker Compose一键部署基础设施,确保环境一致。

创建docker-compose.yml文件:

``` version: '3.8' services: postgres: image: postgres:15-alpine environment: POSTGRES_DB: digital_archive POSTGRES_USER: archive_admin POSTGRES_PASSWORD: YourStrong@Pass123 volumes: - postgres_data:/var/lib/postgresql/data ports: - "5432:5432" elasticsearch: image: elasticsearch:8.11.0 environment: - discovery.type=single-node - xpack.security.enabled=false - "ES_JAVA_OPTS=-Xms512m -Xmx512m" ports: - "9200:9200" volumes: - es_data:/usr/share/elasticsearch/data minio: image: minio/minio:latest command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: minioadmin MINIO_ROOT_PASSWORD: minioadmin123 ports: - "9000:9000" - "9001:9001" volumes: - minio_data:/data volumes: postgres_data: es_data: minio_data: ```

在终端执行docker-compose up -d启动所有服务。

二、数据库与存储初始化

2.1 创建核心数据表

连接PostgreSQL数据库,执行以下SQL创建档案核心表:

``` CREATE TABLE archive_category ( id SERIAL PRIMARY KEY, code VARCHAR(50) UNIQUE NOT NULL, name VARCHAR(100) NOT NULL, parent_id INTEGER REFERENCES archive_category(id), retention_years INTEGER NOT NULL DEFAULT 10, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE archive_record ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title VARCHAR(500) NOT NULL, category_code VARCHAR(50) NOT NULL REFERENCES archive_category(code), file_key VARCHAR(255) NOT NULL, original_filename VARCHAR(255) NOT NULL, file_size BIGINT NOT NULL, mime_type VARCHAR(100), metadata JSONB, status VARCHAR(20) DEFAULT 'DRAFT', created_by VARCHAR(100) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_archive_category ON archive_record(category_code); CREATE INDEX idx_archive_status ON archive_record(status); CREATE INDEX idx_archive_created ON archive_record(created_at); ```

2.2 配置MinIO存储桶

访问http://localhost:9001,使用minioadmin/minioadmin123登录。

创建存储桶:点击“Buckets” -> “Create Bucket”,输入桶名tech-archive,版本控制选择“Enable”。

设置访问策略:进入桶设置,在“Access Policy”中添加以下JSON策略,允许服务端上传下载:

``` { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "", "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::tech-archive/" } ] } ```

三、后端服务搭建

3.1 项目初始化与依赖配置

使用Spring Initializr创建项目,选择依赖:Spring Web, Spring Data JPA, Spring Data Elasticsearch, Validation。

pom.xml中添加MinIO和数据库驱动:

``` io.minio minio 8.5.2 org.postgresql postgresql runtime ```

3.2 核心配置文件

科技部门数字档案馆系统:从零搭建到文件自动化归档实操指南

创建application.yml

``` spring: datasource: url: jdbc:postgresql://localhost:5432/digital_archive username: archive_admin password: YourStrong@Pass123 driver-class-name: org.postgresql.Driver jpa: hibernate: ddl-auto: validate properties: hibernate: dialect: org.hibernate.dialect.PostgreSQLDialect jdbc: lob: non_contextual_creation: true elasticsearch: uris: http://localhost:9200 minio: endpoint: http://localhost:9000 accessKey: minioadmin secretKey: minioadmin123 bucket: tech-archive ```

3.3 实现文件上传服务

创建MinioService.java

``` @Service public class MinioService { @Value("${minio.endpoint}") private String endpoint; @Value("${minio.accessKey}") private String accessKey; @Value("${minio.secretKey}") private String secretKey; @Value("${minio.bucket}") private String bucket; private MinioClient minioClient; @PostConstruct public void init() throws Exception { minioClient = MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); } public String uploadFile(MultipartFile file, String objectName) throws Exception { // 检查存储桶是否存在 boolean found = minioClient.bucketExists(BucketExistsArgs.builder() .bucket(bucket).build()); if (!found) { minioClient.makeBucket(MakeBucketArgs.builder() .bucket(bucket).build()); } // 上传文件 minioClient.putObject( PutObjectArgs.builder() .bucket(bucket) .object(objectName) .stream(file.getInputStream(), file.getSize(), -1) .contentType(file.getContentType()) .build()); return objectName; } public String getFileUrl(String objectName) { return endpoint + "/" + bucket + "/" + objectName; } } ```

3.4 实现档案归档API

创建ArchiveController.java

``` @RestController @RequestMapping("/api/archive") public class ArchiveController { @Autowired private ArchiveService archiveService; @PostMapping("/upload") public ResponseEntity uploadArchive( @RequestParam("file") MultipartFile file, @RequestParam String title, @RequestParam String categoryCode, @RequestParam(required = false) String createdBy) { ArchiveRecord record = archiveService.saveArchive( file, title, categoryCode, createdBy); return ResponseEntity.ok(record); } @GetMapping("/search") public ResponseEntity> search( @RequestParam String keyword, @RequestParam(required = false) String categoryCode) { List records = archiveService .searchArchives(keyword, categoryCode); return ResponseEntity.ok(records); } } ```

四、前端管理界面开发

4.1 安装必要依赖

创建Vue项目并安装Element Plus和Axios:

``` npm create vue@latest digital-archive-admin cd digital-archive-admin npm install element-plus @element-plus/icons-vue axios npm install ```

4.2 实现文件上传组件

创建ArchiveUpload.vue

``` ```

五、自动化归档流程配置

5.1 设置定时扫描任务

创建AutoArchiveScheduler.java

``` @Component public class AutoArchiveScheduler { @Autowired private ArchiveService archiveService; @Value("${archive.scan.path:/data/to-archive}") private String scanPath; @Scheduled(cron = "0 0 2 ?") // 每天凌晨2点执行 public void autoArchiveFiles() { Path scanDir = Paths.get(scanPath); try (Stream paths = Files.walk(scanDir)) { paths.filter(Files::isRegularFile) .forEach(this::processFile); } catch (IOException e) { log.error("扫描目录失败", e); } } private void processFile(Path filePath) { try { String filename = filePath.getFileName().toString(); // 从文件名解析分类和标题 ArchiveInfo info = parseFilename(filename); // 上传到MinIO String objectKey = archiveService.uploadToStorage(filePath); // 保存元数据 archiveService.saveMetadata(info, objectKey); // 移动已处理文件 Files.move(filePath, Paths.get(scanPath, "processed", filename)); } catch (Exception e) { log.error("处理文件失败: " + filePath, e); // 移动到失败目录 try { Files.move(filePath, Paths.get(scanPath, "failed", filename)); } catch (IOException ex) { log.error("移动失败文件出错", ex); } } } } ```

5.2 配置监控与告警

application.yml中添加监控配置:

``` management: endpoints: web: exposure: include: health,metrics,prometheus metrics: export: prometheus: enabled: true archive: monitor: 存储空间告警阈值(GB) storage-alert-threshold: 100 每日归档数量阈值 daily-count-threshold: 1000 ```

六、系统部署与验证

6.1 构建与打包

后端打包:mvn clean package -DskipTests

前端构建:npm run build

6.2 部署配置

创建docker-compose.prod.yml生产环境配置:

``` version: '3.8' services: archive-backend: build: ./backend ports: - "8080:8080" environment: SPRING_PROFILES_ACTIVE: prod depends_on: - postgres - elasticsearch - minio archive-frontend: image: nginx:alpine ports: - "80:80" volumes: - ./frontend/dist:/usr/share/nginx/html - ./nginx.conf:/etc/nginx/nginx.conf ```

6.3 验证步骤

  1. 服务健康检查:访问http://localhost:8080/actuator/health,确认所有组件状态为UP。
  2. 文件上传测试:通过前端界面上传测试文件,确认文件成功存入MinIO且元数据存入数据库。
  3. 搜索功能验证:在前端搜索框输入测试关键词,确认能从Elasticsearch返回正确结果。
  4. 自动化流程测试:在/data/to-archive目录放入测试文件,等待定时任务执行或手动触发,确认文件被自动归档。
AI咨询
热线电话

028-85154420

15388110056

全国售前咨询电话

扫码咨询
安答联动微信公众号二维码

微信扫码关注安答联动

申请试用
热线电话
申请试用

安答联动档案管理系统