技术背景与标准选型
在开发或升级档案管理系统时,必须严格遵循国家标准以确保数据的长期可读性与法律效力。本指南以DA/T 46-2024《电子档案管理通用要求》为核心技术依据,结合DA/T 31-2017《电子档案存储格式规范》,通过Python原生库实现一套符合国标的电子档案存储包构建方案。该方案不依赖任何第三方商业软件,确保零门槛落地。
国标核心要求在于实现电子档案的“四性”检测(真实性、完整性、可用性、安全性),并规范了物理存储结构与元数据描述。本指南将重点解决如何通过代码自动生成符合标准的目录结构、元数据XML文件及数字摘要。
环境准备与工具安装
本实操方案基于Python 3.8+环境,利用其标准库即可完成所有操作,无需安装额外的复杂依赖。请确保你的开发环境已配置好Python。
1. 检查Python版本
打开终端或命令行,输入以下命令确认版本:
```bash
python --version
```
如果版本低于3.8,请前往Python官网下载最新版安装。建议使用VS Code作为编辑器,安装Python插件即可。
2. 创建项目目录
在本地磁盘创建一个工作目录,例如national_standard_archive,并在其中创建main.py文件。我们将在此文件中编写核心逻辑。
核心标准解析与目录结构设计
根据DA/T 46-2024,电子档案的存储必须采用“存储包”形式。一个标准的电子档案存储包应包含电子文件、元数据文件、目录文件及必要的日志信息。
物理存储结构规范
标准规定的目录结构通常采用树状层级,推荐结构如下:
- 存储包根目录/
- 电子文件/(存放原文,如PDF、OFD)
- 元数据/(存放XML元数据描述文件)
- 日志/(可选,存放处理日志)
- 说明文件.txt(可选,包说明)
对于档案的命名,标准要求使用档号作为唯一标识符。档号通常由全宗号-门类代码-年度-保管期限-机构问题-件号组成,例如:001-WS-2023-30Y-001-0001。
电子文件命名规范
放入“电子文件”文件夹的原文,其文件名必须与档号保持一致,仅扩展名不同。例如,如果档号是001-WS-2023-30Y-001-0001,那么PDF文件必须命名为001-WS-2023-30Y-001-0001.pdf。
元数据XML模板构建
元数据是档案管理的核心,DA/T 46-2024明确了必填的元数据元素。我们需要构建一个XML模板,包含以下核心字段:
- 档号:唯一标识。
- 题名:文件标题。
- 责任者:文件形成单位或个人。
- 日期:文件形成日期(YYYYMMDD格式)。
- 页数:文件总页数。
- 格式:电子文件格式标识(如PDF)。
- 大小:文件字节数。
- 原文存储路径:相对于包根目录的路径。
- 电子签名:用于验证真实性的哈希值。
核心元数据字段定义
我们将使用Python的xml.etree.ElementTree模块动态生成XML。这比手动拼接字符串更安全且符合规范。XML的根节点通常定义为电子档案或Record,命名空间可根据实际交换需求定义,此处为了演示清晰,使用无命名空间的标准标签。
完整代码实现与落地
以下代码实现了一个完整的自动化脚本,能够根据输入的档案信息,自动创建符合DA/T 46-2024标准的存储包目录,生成元数据XML,并计算原文的SHA-256哈希值以确保真实性。
Python核心脚本编写

请将以下代码完整复制到main.py中。代码中包含详细的中文注释,解释了每一步与国标的对应关系。
```python
import os
import hashlib
import xml.etree.ElementTree as ET
from xml.dom import minidom
def calculate_file_hash(file_path):
"""
计算文件的SHA-256哈希值,用于确保电子档案的真实性(防篡改)。
符合DA/T 46对电子档案长期保存中技术参数的要求。
"""
sha256_hash = hashlib.sha256()
with open(file_path, "rb") as f:
分块读取文件,避免大文件内存溢出
for byte_block in iter(lambda: f.read(4096), b""):
sha256_hash.update(byte_block)
return sha256_hash.hexdigest()
def create_standard_archive_package(base_path, archive_info):
"""
创建符合国标DA/T 46-2024的电子档案存储包
:param base_path: 存储包根目录
:param archive_info: 档案元数据字典
"""
1. 构建档号 (标准核心标识符)
结构:全宗号-门类代码-年度-保管期限-机构问题-件号
fonds_code = archive_info.get('fonds_code', '001')
category_code = archive_info.get('category_code', 'WS') WS代表文书
year = archive_info.get('year', '2023')
retention = archive_info.get('retention', '30Y')
org_issue = archive_info.get('org_issue', '001')
item_no = archive_info.get('item_no', '0001')
archive_code = f"{fonds_code}-{category_code}-{year}-{retention}-{org_issue}-{item_no}"
2. 创建物理目录结构 (符合DA/T 46存储包规范)
package_root = os.path.join(base_path, archive_code)
电子文件_dir = os.path.join(package_root, "电子文件")
元数据_dir = os.path.join(package_root, "元数据")
os.makedirs(电子文件_dir, exist_ok=True)
os.makedirs(元数据_dir, exist_ok=True)
3. 模拟生成或处理电子原文
实际场景中,这里应该是移动已有文件。为了演示,我们创建一个示例PDF文件。
file_ext = ".pdf"
file_name = f"{archive_code}{file_ext}"
target_file_path = os.path.join(电子文件_dir, file_name)
如果文件不存在,创建一个模拟文件
if not os.path.exists(target_file_path):
with open(target_file_path, 'w', encoding='utf-8') as f:
f.write(f"这是模拟的电子文件内容:{archive_info['title']}")
4. 计算元数据技术参数
file_size = os.path.getsize(target_file_path)
file_hash = calculate_file_hash(target_file_path)
5. 构建元数据XML (符合DA/T 46元数据方案)
root = ET.Element("电子档案")
基础信息段
basic_info = ET.SubElement(root, "基础信息")
ET.SubElement(basic_info, "档号").text = archive_code
ET.SubElement(basic_info, "题名").text = archive_info.get('title')
ET.SubElement(basic_info, "责任者").text = archive_info.get('creator')
ET.SubElement(basic_info, "日期").text = archive_info.get('date') YYYYMMDD
ET.SubElement(basic_info, "页数").text = str(archive_info.get('page_count', 1))
电子文件技术参数段
tech_info = ET.SubElement(root, "电子文件技术参数")
ET.SubElement(tech_info, "格式").text = "PDF"
ET.SubElement(tech_info, "大小").text = str(file_size)
ET.SubElement(tech_info, "原文存储路径").text = f"电子文件/{file_name}"
ET.SubElement(tech_info, "摘要算法").text = "SHA-256"
ET.SubElement(tech_info, "电子签名").text = file_hash
6. 美化XML输出并保存
国标要求XML文件编码必须为UTF-8且无BOM
xml_str = ET.tostring(root, encoding='utf-8')
dom = minidom.parseString(xml_str)
pretty_xml = dom.toprettyxml(indent=" ", encoding='UTF-8')
去除minidom自动生成的空行(可选,为了整洁)
pretty_xml_str = pretty_xml.decode('utf-8').replace('\n\n', '\n')
metadata_filename = f"{archive_code}.xml"
metadata_path = os.path.join(元数据_dir, metadata_filename)
with open(metadata_path, 'w', encoding='utf-8') as f:
f.write(pretty_xml_str)
print(f"成功创建标准档案包: {package_root}")
print(f"元数据文件: {metadata_path}")
print(f"电子文件哈希(SHA-256): {file_hash}")
执行入口
if __name__ == "__main__":
定义一条档案数据
sample_data = {
'title': '关于2023年度技术升级的实施方案',
'creator': '技术研发部',
'date': '20231201',
'page_count': 5,
'year': '2023',
'item_no': '0005'
}
在当前目录下生成output文件夹
output_dir = os.path.join(os.getcwd(), "output")
create_standard_archive_package(output_dir, sample_data)
```
代码执行与结果验证
保存文件后,在终端运行以下命令执行脚本:
```bash
python main.py
```
预期结果:
1. 脚本会在当前目录下生成一个output文件夹。
2. 在output下,你会看到一个以档号命名的文件夹,例如001-WS-2023-30Y-001-0005。
3. 打开该文件夹,你会看到标准的电子文件和元数据子目录。
4. 进入元数据目录,打开XML文件,你将看到结构化清晰的元数据,其中电子签名字段记录了原文的哈希值。
合规性校验与自动化测试
生成符合标准的包只是第一步,DA/T 46-2024 强调了“四性检测”。我们需要编写一个简单的校验函数,来验证刚才生成的包是否合规。
请在main.py中追加以下校验函数,并在执行入口调用它:
```python
def validate_archive_package(package_path):
"""
简单的合规性校验逻辑
1. 检查目录结构是否存在
2. 检查XML元数据是否存在
3. 检查电子文件是否存在
4. 验证哈希值是否匹配(真实性校验)
"""
print(f"\n开始校验档案包: {package_path} ...")
1. 结构检查
电子文件_dir = os.path.join(package_path, "电子文件")
元数据_dir = os.path.join(package_path, "元数据")
if not os.path.exists(电子文件_dir) or not os.path.exists(元数据_dir):
print("[失败] 目录结构不符合国标要求,缺少'电子文件'或'元数据'文件夹。")
return False
2. 查找XML文件
xml_files = [f for f in os.listdir(元数据_dir) if f.endswith('.xml')]
if len(xml_files) == 0:
print("[失败] 元数据目录中未找到XML描述文件。")
return False
xml_path = os.path.join(元数据_dir, xml_files[0])
3. 解析XML获取哈希和路径
try:
tree = ET.parse(xml_path)
root = tree.getroot()
使用XPath或遍历查找节点(这里用遍历以兼容无命名空间情况)
stored_hash = None
file_rel_path = None
for elem in root.iter():
if elem.tag == "电子签名":
stored_hash = elem.text
if elem.tag == "原文存储路径":
file_rel_path = elem.text
if not stored_hash or not file_rel_path:
print("[失败] XML元数据缺少关键字段(电子签名或原文存储路径)。")
return False
4. 定位原文并计算实时哈希
注意:XML中存的是相对路径 "电子文件/xxx.pdf",需要拼接package_path
但由于XML里路径是"电子文件/...",我们需要去掉第一层目录或直接拼接
简单处理:直接在package_path下拼接file_rel_path
target_file = os.path.join(package_path, file_rel_path.replace("/", os.sep))
if not os.path.exists(target_file):
print(f"[失败] 原文文件丢失: {target_file}")
return False
current_hash = calculate_file_hash(target_file)
if current_hash == stored_hash:
print("[成功] 档案包校验通过。目录结构完整,元数据齐全,电子文件真实性验证(哈希匹配)成功。")
return True
else:
print("[失败] 真实性校验失败!电子文件已被篡改或哈希计算错误。")
return False
except Exception as e:
print(f"[失败] 解析XML异常: {e}")
return False
```
更新执行入口代码,在生成后立即进行校验:
```python
... (之前的代码) ...
output_dir = os.path.join(os.getcwd(), "output")
created_path = os.path.join(output_dir, f"001-WS-2023-30Y-001-{sample_data['item_no']}")
create_standard_archive_package(output_dir, sample_data)
validate_archive_package(created_path)
```
总结
通过以上步骤,我们实现了一个完全符合DA/T 46-2024国家标准的电子档案管理核心逻辑。这套方案包含了:
1. 标准化的目录树构建:严格遵循全宗号-门类代码等层级结构。
2. 完整的元数据封装:利用XML记录了档号、责任者、日期等核心业务数据。
3. 自动化的真实性保障:通过SHA-256算法自动计算并校验电子签名,防止数据被篡改。
开发者可以直接将上述create_standard_archive_package函数集成到现有的文件上传接口中,即可在业务系统中零门槛落地国家标准,无需采购昂贵的专用中间件。对于长期保存,建议将生成的存储包进一步打包为ZIP或挂载到对象存储中,并定期运行校验脚本以确保数据安全。