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

从零搭建消防许可证数字档案馆系统 小白落地实操全步骤

发布时间:2026年09月11日 15:55:30 浏览量:0

一、前期准备与环境配置

本次使用轻量级开源方案搭建,硬件要求:2核4G以上云服务器/本地虚拟机,500G以上系统盘(存储原始扫描件),50G以上SSD数据盘(存索引和缩略图);软件依赖:Ubuntu 22.04 LTS、Docker 24.0+、Docker Compose 2.20+、已备案域名(可选,仅用于外网访问)。

1.1 服务器基础环境初始化

1.2 Docker与Docker Compose安装

使用官方一键脚本安装Docker:curl -fsSL https://get.docker.com | sudo sh

将当前用户加入docker组避免每次sudo:sudo usermod -aG docker $USER,然后执行newgrp docker即时生效

安装Docker Compose:sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

赋予执行权限:sudo chmod +x /usr/local/bin/docker-compose

验证安装:docker --version && docker-compose --version,返回版本号即为成功

二、系统核心组件部署

核心组件选择:MongoDB 6.0(存许可证元数据)、MinIO(存扫描件/缩略图对象存储)、自建轻量Web管理后端(用Python Flask写最简逻辑)、前端用HTML+CSS+Bootstrap5(无需复杂框架)

2.1 创建项目目录结构

在服务器用户目录下执行:

2.2 编写Docker Compose配置文件

创建并编辑docker-compose.yml:vim docker-compose.yml,按i键进入编辑模式,完整内容如下:

version: '3.8'
services:
mongo:
image: mongo:6.0
container_name: fire-mongo
restart: always
volumes:
- ./mongo/data:/data/db
environment:
MONGO_INITDB_ROOT_USERNAME: fire_admin
MONGO_INITDB_ROOT_PASSWORD: Fire_Archive_202X!
MONGO_INITDB_DATABASE: fire_license_db
ports:
- "27017:27017"
minio:
image: minio/minio:latest
container_name: fire-minio
restart: always
volumes:
- ./minio/data:/data
- ./minio/config:/root/.minio
environment:
MINIO_ROOT_USER: minio_admin
MINIO_ROOT_PASSWORD: Fire_Minio_202X!
command: server /data --console-address ":9001"
ports:
- "9000:9000"
- "9001:9001"
backend:
image: python:3.11-slim
container_name: fire-backend
restart: always
volumes:
- ./backend:/app
- ./static:/app/static
working_dir: /app
ports:
- "5000:5000"
command: bash -c "pip install -r requirements.txt && python app.py"

编辑完成后按Esc键,输入:wq保存退出

2.3 初始化MongoDB数据库与MinIO存储桶

三、后端与前端代码实现

3.1 后端代码编写

先创建依赖文件:vim ~/fire-license-archive/backend/requirements.txt,内容如下:

flask==2.3.3
flask-cors==4.0.0
pymongo==4.5.0
minio==7.2.0
Pillow==10.1.0
werkzeug==2.3.7

再创建后端主文件:vim ~/fire-license-archive/backend/app.py,完整内容如下:

from flask import Flask, request, jsonify, send_from_directory
from flask_cors import CORS
from pymongo import MongoClient
from minio import Minio
from PIL import Image
import os
import io
import uuid
from datetime import datetime
app = Flask(__name__)
CORS(app)
配置项
MONGO_URI = "mongodb://fire_admin:Fire_Archive_202X!@mongo:27017/"
MINIO_ENDPOINT = "minio:9000"
MINIO_ACCESS_KEY = "minio_admin"
MINIO_SECRET_KEY = "Fire_Minio_202X!"
MINIO_BUCKET = "fire-license-assets"
UPLOAD_DIR = "/app/static/uploads"
THUMB_DIR = "/app/static/thumbs"
THUMB_SIZE = (300, 200)
初始化MongoDB
mongo_client = MongoClient(MONGO_URI)
db = mongo_client["fire_license_db"]
collection = db["licenses"]
初始化MinIO
minio_client = Minio(
MINIO_ENDPOINT,
access_key=MINIO_ACCESS_KEY,
secret_key=MINIO_SECRET_KEY,
secure=False
)
确保目录存在
os.makedirs(UPLOAD_DIR, exist_ok=True)
os.makedirs(THUMB_DIR, exist_ok=True)
上传许可证
@app.route("/api/upload", methods=["POST"])
def upload_license():
try:
data = request.form
file = request.files["file"]
if not file:
return jsonify({"code": 400, "msg": "请上传扫描件"}), 400
生成唯一文件名
ext = file.filename.split(".")[-1].lower()
if ext not in ["jpg", "jpeg", "png", "pdf"]:
return jsonify({"code": 400, "msg": "仅支持jpg/jpeg/png/pdf格式"}), 400
filename = f"{uuid.uuid4().hex}.{ext}"
thumb_filename = f"{uuid.uuid4().hex}.jpg"
上传到MinIO
minio_client.put_object(
MINIO_BUCKET,
filename,
file.stream,
length=-1,
part_size=1010241024,
content_type=file.content_type
)
生成缩略图(仅图片)
thumb_path = None
if ext in ["jpg", "jpeg", "png"]:
img = Image.open(file.stream)
img.thumbnail(THUMB_SIZE)
thumb_path = os.path.join(THUMB_DIR, thumb_filename)
img.save(thumb_path, "JPEG")
存入元数据
license_data = {
"_id": str(uuid.uuid4().hex),
"license_number": data.get("license_number", ""),
"company_name": data.get("company_name", ""),
"address": data.get("address", ""),
"issue_date": data.get("issue_date", ""),
"expiry_date": data.get("expiry_date", ""),
"file_url": f"http://{MINIO_ENDPOINT}/{MINIO_BUCKET}/{filename}",
"thumb_url": f"/static/thumbs/{thumb_filename}" if thumb_path else None,
"create_time": datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
}
collection.insert_one(license_data)
return jsonify({"code": 200, "msg": "上传成功", "data": license_data})
except Exception as e:
return jsonify({"code": 500, "msg": str(e)}), 500
查询许可证
@app.route("/api/list", methods=["GET"])
def list_licenses():
try:
license_number = request.args.get("license_number", "")
company_name = request.args.get("company_name", "")
query = {}
if license_number:
query["license_number"] = {"$regex": license_number, "$options": "i"}
if company_name:
query["company_name"] = {"$regex": company_name, "$options": "i"}
licenses = list(collection.find(query, {"_id": 0}))
return jsonify({"code": 200, "data": licenses})
except Exception as e:
return jsonify({"code": 500, "msg": str(e)}), 500
静态文件服务
@app.route("/static/")
def static_files(path):
return send_from_directory("/app/static", path)
前端入口
@app.route("/")
def index():
return send_from_directory("/app", "index.html")
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)

3.2 前端代码编写

创建前端入口文件:vim ~/fire-license-archive/backend/index.html,完整内容省略CSS框架引用(自行复制Bootstrap5 CDN到),核心表单与列表代码如下:


消防许可证数字档案馆系统

新增许可证
缩略图许可证编号单位名称有效期至操作

Bootstrap5 CDN内容:,插入到index.html的标签内

四、系统启动与验证

微信咨询
电话联系
QQ客服
微信咨询一对一服务
服务热线: 028-8744 4417
QQ客服: 2305721818