数字档案馆系统品牌自建与部署技术实操指南

一、技术架构选型与环境准备

构建企业级数字档案馆系统,核心在于解决海量非结构化数据的存储、元数据管理以及全文检索能力。本文采用Spring Boot 3.x + Vue 3 + MinIO + Elasticsearch的技术栈,实现一套符合OAIS参考模型的自建系统。

1. 基础环境安装

在开始编码前,需在服务器(推荐CentOS 7.9或Ubuntu 20.04)上安装以下基础组件。请直接执行以下命令:

安装JDK 17(后端运行环境):

```bash wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.rpm sudo rpm -ivh jdk-17_linux-x64_bin.rpm ```

安装Docker及Docker Compose(用于部署中间件):

```bash curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose ```

安装Node.js 18(前端构建环境):

```bash curl -fsSL https://rpm.nodesource.com/setup_18.x | sudo bash - sudo yum install -y nodejs ```

二、数据库设计与初始化

数字档案馆的核心在于档案实体的定义。我们使用MySQL 8.0作为元数据存储库。以下SQL脚本包含了档案门类表和档案实体表的设计,支持自定义字段扩展。

1. 创建数据库与表结构

请在MySQL客户端中直接执行以下SQL语句:

```sql CREATE DATABASE digital_archive CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE digital_archive; -- 档案门类定义表(用于定义文书、照片、录音等不同类型) CREATE TABLE archive_category ( id BIGINT PRIMARY KEY AUTO_INCREMENT, category_code VARCHAR(50) NOT NULL COMMENT '门类编码,如: WS, ZP', category_name VARCHAR(100) NOT NULL COMMENT '门类名称', metadata_config JSON COMMENT '元数据字段配置JSON', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_code (category_code) ) ENGINE=InnoDB; -- 档案实体主表 CREATE TABLE archive_record ( id BIGINT PRIMARY KEY AUTO_INCREMENT, category_id BIGINT NOT NULL COMMENT '关联的门类ID', title VARCHAR(255) NOT NULL COMMENT '题名', archive_code VARCHAR(100) COMMENT '档号', file_path VARCHAR(500) COMMENT '原始文件存储路径', file_hash VARCHAR(64) COMMENT '文件SHA256校验值', file_size BIGINT COMMENT '文件大小(字节)', status TINYINT DEFAULT 0 COMMENT '状态: 0-草稿, 1-已归档', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_category (category_id), INDEX idx_code (archive_code) ) ENGINE=InnoDB; -- 插入默认门类数据 INSERT INTO archive_category (category_code, category_name, metadata_config) VALUES ('WS', '文书档案', '[{"field":"year","label":"年度","type":"int"},{"field":"retention","label":"保管期限","type":"string"}]'); ```

三、后端核心功能开发

后端使用Spring Boot 3.2进行开发。我们需要实现文件上传、元数据保存以及对象存储的集成。

1. 项目依赖配置

pom.xml中添加必要的依赖,确保版本一致以避免冲突:

```xml org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-jpa mysql mysql-connector-java 8.0.33 io.minio minio 8.5.7 org.projectlombok lombok true ```

2. 配置文件设置

src/main/resources/application.yml中配置数据库连接及MinIO参数。请确保IP地址和密码与实际环境一致:

```yaml server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/digital_archive?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: YourStrongPassword123 driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: update show-sql: true minio: endpoint: http://localhost:9000 accessKey: minioadmin secretKey: minioadmin bucketName: archive-files ```

3. 文件上传与归档核心代码

创建ArchiveService.java,实现文件上传至MinIO并将元数据落库的逻辑。这是系统最核心的实操部分:

```java package com.digital.archive.service; import io.minio.MinioClient; import io.minio.PutObjectArgs; import io.minio.RemoveObjectArgs; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.InputStream; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.UUID; @Service public class StorageService { @Value("${minio.endpoint}") private String endpoint; @Value("${minio.accessKey}") private String accessKey; @Value("${minio.secretKey}") private String secretKey; @Value("${minio.bucketName}") private String bucketName; public MinioClient getClient() { return MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); } / 上传文件并返回存储路径 / public String uploadFile(MultipartFile file, String categoryCode) throws Exception { MinioClient minioClient = getClient(); String fileName = file.getOriginalFilename(); // 构建层级存储路径:门类/年月/UUID_文件名 String datePath = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMM")); String objectName = categoryCode + "/" + datePath + "/" + UUID.randomUUID() + "_" + fileName; try (InputStream inputStream = file.getInputStream()) { minioClient.putObject( PutObjectArgs.builder() .bucket(bucketName) .object(objectName) .stream(inputStream, file.getSize(), -1) .contentType(file.getContentType()) .build() ); } return objectName; } / 删除文件 / public void deleteFile(String objectName) throws Exception { MinioClient minioClient = getClient(); minioClient.removeObject( RemoveObjectArgs.builder() .bucket(bucketName) .object(objectName) .build() ); } } ```

数字档案馆系统品牌自建与部署技术实操指南

创建ArchiveController.java,对外暴露REST API接口:

```java package com.digital.archive.controller; import com.digital.archive.entity.ArchiveRecord; import com.digital.archive.repository.ArchiveRecordRepository; import com.digital.archive.service.StorageService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.; import org.springframework.web.multipart.MultipartFile; import java.util.Optional; @RestController @RequestMapping("/api/archive") public class ArchiveController { @Autowired private StorageService storageService; @Autowired private ArchiveRecordRepository repository; / 档案归档接口 / @PostMapping("/upload") public String uploadArchive( @RequestParam("file") MultipartFile file, @RequestParam("title") String title, @RequestParam("categoryId") Long categoryId) { try { // 1. 上传文件到对象存储 String categoryCode = "WS"; // 实际应根据categoryId查询 String filePath = storageService.uploadFile(file, categoryCode); // 2. 保存元数据到数据库 ArchiveRecord record = new ArchiveRecord(); record.setCategoryId(categoryId); record.setTitle(title); record.setFilePath(filePath); record.setFileSize(file.getSize()); record.setStatus(1); // 已归档 repository.save(record); return "归档成功,文件ID: " + record.getId(); } catch (Exception e) { e.printStackTrace(); return "归档失败: " + e.getMessage(); } } } ```

四、对象存储与检索中间件部署

使用Docker Compose一键部署MinIO(文件存储)和Elasticsearch(全文检索)。创建docker-compose.yml文件:

```yaml version: '3.8' services: minio: image: minio/minio:latest container_name: digital_minio ports: - "9000:9000" - "9001:9001" environment: MINIO_ROOT_USER: minioadmin MINIO_ROOT_PASSWORD: minioadmin command: server /data --console-address ":9001" volumes: - minio_data:/data elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0 container_name: digital_es ports: - "9200:9200" environment: - discovery.type=single-node - xpack.security.enabled=false - "ES_JAVA_OPTS=-Xms512m -Xmx512m" volumes: - es_data:/usr/share/elasticsearch/data volumes: minio_data: es_data: ```

启动中间件服务:

```bash docker-compose up -d ```

启动后,访问 http://服务器IP:9001 可进入MinIO控制台管理文件。为了确保Java后端能正常连接,请提前在MinIO控制台中创建名为archive-files的Bucket。

五、前端交互界面实现

使用Vue 3和Element Plus构建简单的上传界面。执行以下命令初始化项目:

```bash npm create vue@latest archive-frontend cd archive-frontend npm install element-plus axios ```

修改src/App.vue,编写完整的上传组件代码:

```html ```

启动前端服务进行测试:

```bash npm run dev ``>

六、系统部署与验证

完成开发后,将后端打包为JAR包,前端打包为静态资源并部署至Nginx。

1. 后端打包

在项目根目录执行:

```bash mvn clean package -DskipTests ```

生成的JAR包位于target/目录下。运行命令启动:

```bash java -jar target/your-project-name-0.0.1-SNAPSHOT.jar ```

2. 前端打包与Nginx配置

在前端项目目录执行:

```bash npm run build ```

将生成的dist目录内容上传至服务器的/var/www/archive/。编辑Nginx配置:

```nginx server { listen 80; server_name your-archive-domain.com; location / { root /var/www/archive; index index.html; try_files $uri $uri/ /index.html; } 反向代理后端接口,解决跨域问题 location /api/ { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } ```

重启Nginx使配置生效:

```bash sudo systemctl restart nginx ```
AI咨询
热线电话

028-85154420

15388110056

全国售前咨询电话

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

微信扫码关注安答联动

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

安答联动档案管理系统