调整接口,修正文件名称和数据字段,更新接口文档和定义。
This commit is contained in:
parent
42c254fe51
commit
07812ea8c4
137
MinIO文件位置说明.md
Normal file
137
MinIO文件位置说明.md
Normal file
@ -0,0 +1,137 @@
|
||||
# MinIO文件位置说明
|
||||
|
||||
## ✅ 确认:文件没有被删除!
|
||||
|
||||
测试脚本**只删除了本地临时文件**,**不会删除MinIO上的文件**。所有上传的文件都还在MinIO中。
|
||||
|
||||
---
|
||||
|
||||
## 📍 测试文件位置
|
||||
|
||||
### 1. 测试上传的文件
|
||||
|
||||
找到了 **3个测试文件**,位置在:
|
||||
|
||||
```
|
||||
存储桶: finyx
|
||||
路径前缀: 615873064429507639/TEST/2025/12/
|
||||
```
|
||||
|
||||
具体文件:
|
||||
|
||||
1. **test_file_20251205095549.txt**
|
||||
- 完整路径: `615873064429507639/TEST/2025/12/test_file_20251205095549.txt`
|
||||
- 大小: 122 字节
|
||||
- 上传时间: 2025-12-05 01:55:49
|
||||
|
||||
2. **test_file_20251205095558.txt**
|
||||
- 完整路径: `615873064429507639/TEST/2025/12/test_file_20251205095558.txt`
|
||||
- 大小: 122 字节
|
||||
- 上传时间: 2025-12-05 01:55:58
|
||||
|
||||
3. **test_file_20251205095620.txt**
|
||||
- 完整路径: `615873064429507639/TEST/2025/12/test_file_20251205095620.txt`
|
||||
- 大小: 122 字节
|
||||
- 上传时间: 2025-12-05 01:56:20
|
||||
|
||||
### 2. 模板文件
|
||||
|
||||
找到了 **1个模板文件**:
|
||||
|
||||
- **初步核实审批表模板.docx**
|
||||
- 完整路径: `615873064429507639/TEMPLATE/2025/12/初步核实审批表模板.docx`
|
||||
- 大小: 21101 字节
|
||||
- 上传时间: 2025-12-02 06:42:56
|
||||
|
||||
---
|
||||
|
||||
## 🔍 如何在MinIO中查找文件
|
||||
|
||||
### 方式1:通过MinIO Web界面
|
||||
|
||||
1. 登录MinIO Web界面
|
||||
2. 选择存储桶:`finyx`
|
||||
3. 导航到路径:
|
||||
```
|
||||
finyx/
|
||||
└── 615873064429507639/
|
||||
├── TEST/
|
||||
│ └── 2025/
|
||||
│ └── 12/
|
||||
│ ├── test_file_20251205095549.txt
|
||||
│ ├── test_file_20251205095558.txt
|
||||
│ └── test_file_20251205095620.txt
|
||||
└── TEMPLATE/
|
||||
└── 2025/
|
||||
└── 12/
|
||||
└── 初步核实审批表模板.docx
|
||||
```
|
||||
|
||||
### 方式2:使用查询脚本
|
||||
|
||||
运行检查脚本查看所有文件:
|
||||
|
||||
```bash
|
||||
python check_minio_files.py
|
||||
```
|
||||
|
||||
这个脚本会列出:
|
||||
- 所有测试文件
|
||||
- 所有与租户相关的文件(共442个)
|
||||
- 所有模板文件
|
||||
|
||||
---
|
||||
|
||||
## 📊 文件统计
|
||||
|
||||
- **测试文件**: 3个(在 `TEST/` 目录下)
|
||||
- **模板文件**: 1个(在 `TEMPLATE/` 目录下)
|
||||
- **租户相关文件总数**: 442个
|
||||
|
||||
---
|
||||
|
||||
## 🔗 访问文件
|
||||
|
||||
### 生成访问URL
|
||||
|
||||
如果需要访问这些文件,可以使用以下Python代码生成预签名URL:
|
||||
|
||||
```python
|
||||
from minio import Minio
|
||||
from datetime import timedelta
|
||||
|
||||
client = Minio(
|
||||
'minio.datacubeworld.com:9000',
|
||||
access_key='JOLXFXny3avFSzB0uRA5',
|
||||
secret_key='G1BR8jStNfovkfH5ou39EmPl34E4l7dGrnd3Cz0I',
|
||||
secure=True
|
||||
)
|
||||
|
||||
# 生成访问URL(7天有效)
|
||||
object_name = '615873064429507639/TEST/2025/12/test_file_20251205095620.txt'
|
||||
url = client.presigned_get_object(
|
||||
'finyx',
|
||||
object_name,
|
||||
expires=timedelta(days=7)
|
||||
)
|
||||
print(url)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ 验证结果
|
||||
|
||||
- ✅ 文件确实存在
|
||||
- ✅ 文件没有被删除
|
||||
- ✅ 文件路径正确
|
||||
- ✅ 可以正常访问
|
||||
|
||||
如果您在MinIO界面中找不到,请:
|
||||
1. 确认您查看的是正确的存储桶:`finyx`
|
||||
2. 导航到正确的路径:`615873064429507639/TEST/2025/12/`
|
||||
3. 或者运行 `python check_minio_files.py` 查看详细列表
|
||||
|
||||
---
|
||||
|
||||
**文件都在,请放心!** 🎉
|
||||
|
||||
169
MinIO连接测试结果.md
Normal file
169
MinIO连接测试结果.md
Normal file
@ -0,0 +1,169 @@
|
||||
# MinIO连接测试结果
|
||||
|
||||
## ✅ 测试结果:全部通过
|
||||
|
||||
### 测试时间
|
||||
2025-12-05 09:56:20
|
||||
|
||||
### 测试配置
|
||||
- **端点**: `minio.datacubeworld.com:9000`
|
||||
- **使用HTTPS**: 是
|
||||
- **存储桶**: `finyx`
|
||||
- **访问密钥**: `JOLXFXny3avFSzB0uRA5`
|
||||
- **密钥**: `G1BR8jStNfovkfH5ou39EmPl34E4l7dGrnd3Cz0I`
|
||||
|
||||
---
|
||||
|
||||
## 📋 测试项目结果
|
||||
|
||||
| 测试项目 | 状态 | 说明 |
|
||||
|---------|------|------|
|
||||
| MinIO连接 | ✅ 通过 | 连接成功,可以访问MinIO服务 |
|
||||
| 存储桶存在 | ✅ 通过 | 目标存储桶 `finyx` 存在 |
|
||||
| 列出对象 | ✅ 通过 | 可以正常列出存储桶中的对象 |
|
||||
| 文件上传 | ✅ 通过 | 测试文件上传成功 |
|
||||
| URL生成 | ✅ 通过 | 预签名URL生成成功 |
|
||||
| URL下载 | ✅ 通过 | 通过URL可以成功下载文件 |
|
||||
|
||||
**通过率: 5/5 (100%)**
|
||||
|
||||
---
|
||||
|
||||
## 🔍 详细测试结果
|
||||
|
||||
### 1. 连接测试
|
||||
- ✅ MinIO服务器连接成功
|
||||
- ✅ 可以列出所有存储桶
|
||||
- ✅ 目标存储桶 `finyx` 存在且可访问
|
||||
|
||||
### 2. 文件上传测试
|
||||
- ✅ 成功创建测试文件
|
||||
- ✅ 成功上传到MinIO
|
||||
- ✅ 文件路径: `/615873064429507639/TEST/2025/12/test_file_20251205095620.txt`
|
||||
|
||||
### 3. URL生成测试
|
||||
- ✅ 预签名URL生成成功
|
||||
- ✅ URL有效期: 7天
|
||||
- ✅ URL格式正确,包含所有必要的签名参数
|
||||
|
||||
### 4. 下载测试
|
||||
- ✅ 通过预签名URL可以成功下载文件
|
||||
- ✅ HTTP状态码: 200
|
||||
- ✅ 文件内容完整正确
|
||||
- ✅ 内容类型识别正确: `text/plain; charset=utf-8`
|
||||
|
||||
---
|
||||
|
||||
## 📝 配置验证
|
||||
|
||||
### 正确的配置方式
|
||||
|
||||
```python
|
||||
MINIO_CONFIG = {
|
||||
'endpoint': 'minio.datacubeworld.com:9000', # 注意:去掉协议前缀
|
||||
'access_key': 'JOLXFXny3avFSzB0uRA5',
|
||||
'secret_key': 'G1BR8jStNfovkfH5ou39EmPl34E4l7dGrnd3Cz0I',
|
||||
'secure': True # 使用HTTPS
|
||||
}
|
||||
```
|
||||
|
||||
### 重要提示
|
||||
|
||||
1. **endpoint格式**
|
||||
- ✅ 正确: `minio.datacubeworld.com:9000`
|
||||
- ❌ 错误: `https://minio.datacubeworld.com:9000/`
|
||||
- 说明: endpoint不应该包含协议前缀(`https://`)和末尾斜杠(`/`)
|
||||
|
||||
2. **secure参数**
|
||||
- 设置为 `True` 表示使用HTTPS
|
||||
- 设置为 `False` 表示使用HTTP
|
||||
|
||||
3. **存储桶名称**
|
||||
- 存储桶 `finyx` 已存在,可以直接使用
|
||||
|
||||
---
|
||||
|
||||
## 🔗 URL访问方式
|
||||
|
||||
### 预签名URL(推荐)
|
||||
|
||||
生成预签名URL,有效期7天:
|
||||
|
||||
```python
|
||||
from datetime import timedelta
|
||||
|
||||
url = client.presigned_get_object(
|
||||
bucket_name,
|
||||
object_name,
|
||||
expires=timedelta(days=7)
|
||||
)
|
||||
```
|
||||
|
||||
**特点:**
|
||||
- ✅ 安全,带有签名验证
|
||||
- ✅ 可以设置有效期
|
||||
- ✅ 无需公开存储桶访问权限
|
||||
|
||||
### 公共URL(如果存储桶是公共的)
|
||||
|
||||
```
|
||||
https://minio.datacubeworld.com:9000/finyx/{object_name}
|
||||
```
|
||||
|
||||
**注意:** 这种方式需要存储桶设置为公共访问。
|
||||
|
||||
---
|
||||
|
||||
## 💡 使用建议
|
||||
|
||||
### 1. 文件路径存储
|
||||
|
||||
根据接口文档要求,数据库存储时使用**相对路径**:
|
||||
|
||||
```python
|
||||
# 相对路径格式
|
||||
file_path = "/615873064429507639/TEST/2025/12/test_file.txt"
|
||||
```
|
||||
|
||||
### 2. URL生成
|
||||
|
||||
在实际使用中,建议:
|
||||
- 使用预签名URL进行临时访问
|
||||
- 根据业务需求设置合适的有效期
|
||||
- 不公开存储桶访问权限,保证安全性
|
||||
|
||||
### 3. 文件组织
|
||||
|
||||
建议的文件路径组织方式:
|
||||
```
|
||||
{tenant_id}/TEMPLATE/{year}/{month}/文件名.docx
|
||||
{tenant_id}/GENERATED/{year}/{month}/{document_id}/文件名.docx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ 结论
|
||||
|
||||
**MinIO配置完全正确,可以正常使用!**
|
||||
|
||||
所有功能测试通过:
|
||||
- ✅ 连接正常
|
||||
- ✅ 上传功能正常
|
||||
- ✅ URL生成正常
|
||||
- ✅ 下载功能正常
|
||||
|
||||
可以放心使用此配置进行文档生成和存储。
|
||||
|
||||
---
|
||||
|
||||
## 📄 测试文件
|
||||
|
||||
完整的测试脚本:`test_minio_connection.py`
|
||||
|
||||
可以随时运行此脚本验证MinIO连接状态。
|
||||
|
||||
---
|
||||
|
||||
**测试完成时间**: 2025-12-05 09:56:20
|
||||
**测试状态**: ✅ 全部通过
|
||||
|
||||
Binary file not shown.
43
app.py
43
app.py
@ -461,33 +461,26 @@ def generate_document():
|
||||
example: DOC202411260001
|
||||
documentName:
|
||||
type: string
|
||||
description: 文档名称
|
||||
example: 请示报告卡_张三.docx
|
||||
inputData:
|
||||
type: array
|
||||
description: 输入数据
|
||||
description: 文档名称(第一个生成的文档名称)
|
||||
example: 初步核实审批表_张三.docx
|
||||
fpolicFieldParamFileList:
|
||||
type: array
|
||||
description: 文件列表(包含filePath)
|
||||
description: 生成的文档列表(数量与请求一致)
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
fileId:
|
||||
type: integer
|
||||
description: 文件ID
|
||||
description: 文件ID(与请求中的fileId一致)
|
||||
example: 1
|
||||
fileName:
|
||||
type: string
|
||||
description: 文件名称
|
||||
example: 请示报告卡.doc
|
||||
templateCode:
|
||||
type: string
|
||||
description: 模板编码
|
||||
example: PRELIMINARY_VERIFICATION_APPROVAL
|
||||
description: 实际生成的文档名称(.docx格式),与请求中的fileName可能不同
|
||||
example: 初步核实审批表_张三.docx
|
||||
filePath:
|
||||
type: string
|
||||
description: MinIO相对路径
|
||||
example: /202511261123/请示报告卡.doc
|
||||
description: MinIO相对路径(指向生成的文档文件)
|
||||
example: /615873064429507639/20251205090700/初步核实审批表_张三.docx
|
||||
msg:
|
||||
type: string
|
||||
example: ok
|
||||
@ -561,13 +554,13 @@ def generate_document():
|
||||
if field_code:
|
||||
field_data[field_code] = field_value or ''
|
||||
|
||||
# 生成文档ID和文档名称(使用第一个文件)
|
||||
# 生成文档ID
|
||||
document_id = document_service.generate_document_id()
|
||||
first_file_name = file_list[0].get('fileName', 'document.docx') if file_list else 'document.docx'
|
||||
document_name = document_service.generate_document_name(first_file_name, field_data)
|
||||
|
||||
# 处理每个文件
|
||||
result_file_list = []
|
||||
first_document_name = None # 用于存储第一个生成的文档名
|
||||
|
||||
for file_info in file_list:
|
||||
file_id = file_info.get('fileId')
|
||||
file_name = file_info.get('fileName', '')
|
||||
@ -584,9 +577,16 @@ def generate_document():
|
||||
file_info=file_info
|
||||
)
|
||||
|
||||
# 使用生成的文档名称(.docx格式),而不是原始文件名
|
||||
generated_file_name = result.get('fileName', file_name)
|
||||
|
||||
# 保存第一个文档名作为 documentName
|
||||
if first_document_name is None:
|
||||
first_document_name = generated_file_name
|
||||
|
||||
result_file_list.append({
|
||||
'fileId': file_id,
|
||||
'fileName': file_name,
|
||||
'fileName': generated_file_name, # 使用生成的文档名
|
||||
'filePath': result['filePath']
|
||||
})
|
||||
|
||||
@ -601,11 +601,10 @@ def generate_document():
|
||||
else:
|
||||
return error_response(3001, f"文件生成失败: {error_msg}")
|
||||
|
||||
# 构建返回数据
|
||||
# 构建返回数据(不包含inputData,只返回生成的文档信息)
|
||||
return success_response({
|
||||
'documentId': document_id,
|
||||
'documentName': document_name,
|
||||
'inputData': input_data,
|
||||
'documentName': first_document_name or 'generated.docx', # 使用第一个生成的文档名
|
||||
'fpolicFieldParamFileList': result_file_list
|
||||
})
|
||||
|
||||
|
||||
132
check_minio_files.py
Normal file
132
check_minio_files.py
Normal file
@ -0,0 +1,132 @@
|
||||
"""
|
||||
检查MinIO中是否有测试文件,并列出所有文件
|
||||
"""
|
||||
from minio import Minio
|
||||
from datetime import datetime
|
||||
import os
|
||||
|
||||
# MinIO连接配置
|
||||
MINIO_CONFIG = {
|
||||
'endpoint': 'minio.datacubeworld.com:9000',
|
||||
'access_key': 'JOLXFXny3avFSzB0uRA5',
|
||||
'secret_key': 'G1BR8jStNfovkfH5ou39EmPl34E4l7dGrnd3Cz0I',
|
||||
'secure': True
|
||||
}
|
||||
|
||||
BUCKET_NAME = 'finyx'
|
||||
TENANT_ID = '615873064429507639'
|
||||
|
||||
def check_test_files():
|
||||
"""检查测试文件是否存在"""
|
||||
print("="*60)
|
||||
print("检查MinIO中的测试文件")
|
||||
print("="*60)
|
||||
|
||||
try:
|
||||
# 创建MinIO客户端
|
||||
client = Minio(
|
||||
MINIO_CONFIG['endpoint'],
|
||||
access_key=MINIO_CONFIG['access_key'],
|
||||
secret_key=MINIO_CONFIG['secret_key'],
|
||||
secure=MINIO_CONFIG['secure']
|
||||
)
|
||||
|
||||
# 检查存储桶
|
||||
if not client.bucket_exists(BUCKET_NAME):
|
||||
print(f"✗ 存储桶 '{BUCKET_NAME}' 不存在")
|
||||
return
|
||||
|
||||
print(f"\n✓ 存储桶 '{BUCKET_NAME}' 存在")
|
||||
|
||||
# 查找测试文件(TEST目录下的文件)
|
||||
print(f"\n查找测试文件(路径包含 TEST)...")
|
||||
test_files = []
|
||||
|
||||
objects = client.list_objects(BUCKET_NAME, prefix=f"{TENANT_ID}/TEST/", recursive=True)
|
||||
for obj in objects:
|
||||
test_files.append({
|
||||
'name': obj.object_name,
|
||||
'size': obj.size,
|
||||
'last_modified': obj.last_modified
|
||||
})
|
||||
|
||||
if test_files:
|
||||
print(f"\n找到 {len(test_files)} 个测试文件:")
|
||||
for i, file_info in enumerate(test_files, 1):
|
||||
print(f"\n{i}. 文件名称: {file_info['name']}")
|
||||
print(f" 大小: {file_info['size']} 字节")
|
||||
print(f" 修改时间: {file_info['last_modified']}")
|
||||
|
||||
# 生成访问URL
|
||||
from datetime import timedelta
|
||||
url = client.presigned_get_object(
|
||||
BUCKET_NAME,
|
||||
file_info['name'],
|
||||
expires=timedelta(days=7)
|
||||
)
|
||||
print(f" 访问URL: {url[:100]}...")
|
||||
else:
|
||||
print("\n⚠ 未找到测试文件")
|
||||
print(" 可能原因:")
|
||||
print(" 1. 文件已被删除")
|
||||
print(" 2. 文件路径不同")
|
||||
print(" 3. 文件在其他位置")
|
||||
|
||||
# 列出所有与TENANT_ID相关的文件
|
||||
print(f"\n" + "="*60)
|
||||
print(f"列出所有与租户 {TENANT_ID} 相关的文件")
|
||||
print("="*60)
|
||||
|
||||
all_files = []
|
||||
objects = client.list_objects(BUCKET_NAME, prefix=f"{TENANT_ID}/", recursive=True)
|
||||
for obj in objects:
|
||||
all_files.append({
|
||||
'name': obj.object_name,
|
||||
'size': obj.size,
|
||||
'last_modified': obj.last_modified
|
||||
})
|
||||
|
||||
if all_files:
|
||||
print(f"\n找到 {len(all_files)} 个文件:")
|
||||
for i, file_info in enumerate(all_files[:20], 1): # 只显示前20个
|
||||
print(f"\n{i}. {file_info['name']}")
|
||||
print(f" 大小: {file_info['size']} 字节")
|
||||
print(f" 修改时间: {file_info['last_modified']}")
|
||||
|
||||
if len(all_files) > 20:
|
||||
print(f"\n... 还有 {len(all_files) - 20} 个文件未显示")
|
||||
else:
|
||||
print(f"\n⚠ 未找到与租户 {TENANT_ID} 相关的文件")
|
||||
|
||||
# 检查是否有TEMPLATE目录
|
||||
print(f"\n" + "="*60)
|
||||
print("检查模板文件")
|
||||
print("="*60)
|
||||
|
||||
template_files = []
|
||||
objects = client.list_objects(BUCKET_NAME, prefix=f"{TENANT_ID}/TEMPLATE/", recursive=True)
|
||||
for obj in objects:
|
||||
template_files.append({
|
||||
'name': obj.object_name,
|
||||
'size': obj.size,
|
||||
'last_modified': obj.last_modified
|
||||
})
|
||||
|
||||
if template_files:
|
||||
print(f"\n找到 {len(template_files)} 个模板文件:")
|
||||
for i, file_info in enumerate(template_files, 1):
|
||||
print(f"\n{i}. {file_info['name']}")
|
||||
print(f" 大小: {file_info['size']} 字节")
|
||||
print(f" 修改时间: {file_info['last_modified']}")
|
||||
else:
|
||||
print(f"\n⚠ 未找到模板文件")
|
||||
print(f" 模板文件应该在: {TENANT_ID}/TEMPLATE/ 目录下")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n✗ 检查失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
if __name__ == '__main__':
|
||||
check_test_files()
|
||||
|
||||
117
get_template_url.py
Normal file
117
get_template_url.py
Normal file
@ -0,0 +1,117 @@
|
||||
"""
|
||||
获取模板文件的下载链接
|
||||
"""
|
||||
from minio import Minio
|
||||
from datetime import timedelta
|
||||
import requests
|
||||
|
||||
# MinIO连接配置
|
||||
MINIO_CONFIG = {
|
||||
'endpoint': 'minio.datacubeworld.com:9000',
|
||||
'access_key': 'JOLXFXny3avFSzB0uRA5',
|
||||
'secret_key': 'G1BR8jStNfovkfH5ou39EmPl34E4l7dGrnd3Cz0I',
|
||||
'secure': True
|
||||
}
|
||||
|
||||
BUCKET_NAME = 'finyx'
|
||||
OBJECT_NAME = '615873064429507639/TEMPLATE/2025/12/初步核实审批表模板.docx'
|
||||
|
||||
def get_template_url():
|
||||
"""生成模板文件的下载链接"""
|
||||
print("="*60)
|
||||
print("获取模板文件下载链接")
|
||||
print("="*60)
|
||||
|
||||
try:
|
||||
# 创建MinIO客户端
|
||||
client = Minio(
|
||||
MINIO_CONFIG['endpoint'],
|
||||
access_key=MINIO_CONFIG['access_key'],
|
||||
secret_key=MINIO_CONFIG['secret_key'],
|
||||
secure=MINIO_CONFIG['secure']
|
||||
)
|
||||
|
||||
# 检查文件是否存在
|
||||
print(f"\n检查文件是否存在...")
|
||||
try:
|
||||
stat = client.stat_object(BUCKET_NAME, OBJECT_NAME)
|
||||
print(f"✓ 文件存在")
|
||||
print(f" 文件名: {OBJECT_NAME}")
|
||||
print(f" 文件大小: {stat.size} 字节")
|
||||
print(f" 最后修改: {stat.last_modified}")
|
||||
print(f" 内容类型: {stat.content_type}")
|
||||
except Exception as e:
|
||||
print(f"✗ 文件不存在或无法访问: {e}")
|
||||
return
|
||||
|
||||
# 生成预签名URL(7天有效期)
|
||||
print(f"\n生成预签名URL(7天有效)...")
|
||||
url = client.presigned_get_object(
|
||||
BUCKET_NAME,
|
||||
OBJECT_NAME,
|
||||
expires=timedelta(days=7)
|
||||
)
|
||||
|
||||
print(f"\n" + "="*60)
|
||||
print("下载链接(7天有效)")
|
||||
print("="*60)
|
||||
print(f"\n{url}\n")
|
||||
|
||||
# 生成公共URL(如果存储桶是公共的)
|
||||
protocol = "https" if MINIO_CONFIG['secure'] else "http"
|
||||
public_url = f"{protocol}://{MINIO_CONFIG['endpoint']}/{BUCKET_NAME}/{OBJECT_NAME}"
|
||||
|
||||
print("="*60)
|
||||
print("公共URL(如果存储桶是公共的)")
|
||||
print("="*60)
|
||||
print(f"\n{public_url}\n")
|
||||
|
||||
# 测试下载
|
||||
print("="*60)
|
||||
print("测试下载链接")
|
||||
print("="*60)
|
||||
|
||||
print(f"\n正在测试预签名URL...")
|
||||
try:
|
||||
response = requests.get(url, timeout=10, stream=True)
|
||||
if response.status_code == 200:
|
||||
print(f"✓ 预签名URL可以正常下载")
|
||||
print(f" 状态码: {response.status_code}")
|
||||
print(f" 内容长度: {len(response.content)} 字节")
|
||||
print(f" 内容类型: {response.headers.get('Content-Type', 'N/A')}")
|
||||
else:
|
||||
print(f"✗ 下载失败,状态码: {response.status_code}")
|
||||
except Exception as e:
|
||||
print(f"✗ 下载测试失败: {e}")
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("使用说明")
|
||||
print("="*60)
|
||||
print("\n1. 预签名URL(推荐):")
|
||||
print(f" {url}")
|
||||
print("\n 特点:")
|
||||
print(" - 安全,带有签名验证")
|
||||
print(" - 有效期:7天")
|
||||
print(" - 可以直接在浏览器中打开下载")
|
||||
|
||||
print("\n2. 公共URL(如果存储桶是公共的):")
|
||||
print(f" {public_url}")
|
||||
print("\n 特点:")
|
||||
print(" - 需要存储桶设置为公共访问")
|
||||
print(" - 永久有效(如果存储桶保持公共)")
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("完成")
|
||||
print("="*60)
|
||||
|
||||
return url, public_url
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n✗ 错误: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return None, None
|
||||
|
||||
if __name__ == '__main__':
|
||||
get_template_url()
|
||||
|
||||
Binary file not shown.
@ -232,12 +232,16 @@ class DocumentService:
|
||||
# 填充模板
|
||||
filled_doc_path = self.fill_template(template_path, field_data)
|
||||
|
||||
# 上传到MinIO
|
||||
file_name = file_info.get('fileName', 'generated.docx')
|
||||
file_path = self.upload_to_minio(filled_doc_path, file_name)
|
||||
# 生成文档名称(.docx格式)
|
||||
original_file_name = file_info.get('fileName', 'generated.doc')
|
||||
generated_file_name = self.generate_document_name(original_file_name, field_data)
|
||||
|
||||
# 上传到MinIO(使用生成的文档名)
|
||||
file_path = self.upload_to_minio(filled_doc_path, generated_file_name)
|
||||
|
||||
return {
|
||||
'filePath': file_path
|
||||
'filePath': file_path,
|
||||
'fileName': generated_file_name # 返回生成的文档名
|
||||
}
|
||||
|
||||
finally:
|
||||
|
||||
228
test_document_generation.py
Normal file
228
test_document_generation.py
Normal file
@ -0,0 +1,228 @@
|
||||
"""
|
||||
测试文档生成功能 - 使用虚拟数据生成初步核实审批表
|
||||
"""
|
||||
from services.document_service import DocumentService
|
||||
from datetime import datetime, timedelta
|
||||
from minio import Minio
|
||||
import os
|
||||
|
||||
# 虚拟数据 - 初步核实审批表字段
|
||||
VIRTUAL_DATA = [
|
||||
{"fieldCode": "target_name", "fieldValue": "张三"},
|
||||
{"fieldCode": "target_gender", "fieldValue": "男"},
|
||||
{"fieldCode": "target_nationality", "fieldValue": "汉族"},
|
||||
{"fieldCode": "target_date_of_birth", "fieldValue": "198005"},
|
||||
{"fieldCode": "target_place_of_birth", "fieldValue": "山西太原"},
|
||||
{"fieldCode": "target_political_status", "fieldValue": "中共党员"},
|
||||
{"fieldCode": "target_education", "fieldValue": "本科学历"},
|
||||
{"fieldCode": "target_organization_and_position", "fieldValue": "某公司总经理"},
|
||||
{"fieldCode": "target_id_number", "fieldValue": "140101198005150123"},
|
||||
{"fieldCode": "target_contact", "fieldValue": "13800138000"},
|
||||
{"fieldCode": "target_address", "fieldValue": "山西省太原市小店区某某街道123号"},
|
||||
{"fieldCode": "clue_source", "fieldValue": "群众举报"},
|
||||
{"fieldCode": "clue_info", "fieldValue": "被举报人利用职务便利,违规接受他人请托,收受他人财物"},
|
||||
{"fieldCode": "investigation_reason", "fieldValue": "根据群众举报,反映被核查人存在违规违纪问题"},
|
||||
{"fieldCode": "investigation_basis", "fieldValue": "《中国共产党纪律检查机关监督执纪工作规则》相关规定"},
|
||||
]
|
||||
|
||||
TEMPLATE_CODE = "PRELIMINARY_VERIFICATION_APPROVAL"
|
||||
FILE_NAME = "初步核实审批表_张三.docx"
|
||||
|
||||
def print_section(title):
|
||||
"""打印章节标题"""
|
||||
print("\n" + "="*60)
|
||||
print(f" {title}")
|
||||
print("="*60)
|
||||
|
||||
def print_result(success, message):
|
||||
"""打印测试结果"""
|
||||
status = "✓" if success else "✗"
|
||||
print(f"{status} {message}")
|
||||
|
||||
def test_document_generation():
|
||||
"""测试文档生成"""
|
||||
print_section("文档生成测试 - 初步核实审批表")
|
||||
|
||||
print("\n使用虚拟数据生成文档...")
|
||||
print(f"模板编码: {TEMPLATE_CODE}")
|
||||
print(f"文件名称: {FILE_NAME}")
|
||||
print(f"\n虚拟数据字段数量: {len(VIRTUAL_DATA)}")
|
||||
print("\n字段列表:")
|
||||
for item in VIRTUAL_DATA[:5]: # 只显示前5个
|
||||
print(f" - {item['fieldCode']}: {item['fieldValue']}")
|
||||
print(f" ... 还有 {len(VIRTUAL_DATA) - 5} 个字段")
|
||||
|
||||
try:
|
||||
# 创建文档服务实例
|
||||
doc_service = DocumentService()
|
||||
|
||||
# 准备文件信息
|
||||
file_info = {
|
||||
'fileId': 1,
|
||||
'fileName': FILE_NAME,
|
||||
'templateCode': TEMPLATE_CODE
|
||||
}
|
||||
|
||||
print("\n开始生成文档...")
|
||||
|
||||
# 生成文档
|
||||
result = doc_service.generate_document(
|
||||
template_code=TEMPLATE_CODE,
|
||||
input_data=VIRTUAL_DATA,
|
||||
file_info=file_info
|
||||
)
|
||||
|
||||
print_result(True, "文档生成成功!")
|
||||
|
||||
file_path = result.get('filePath', '')
|
||||
print(f"\n生成的文件路径: {file_path}")
|
||||
|
||||
return file_path
|
||||
|
||||
except Exception as e:
|
||||
print_result(False, f"文档生成失败: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return None
|
||||
|
||||
def generate_download_url(file_path):
|
||||
"""生成下载URL"""
|
||||
print_section("生成下载URL")
|
||||
|
||||
if not file_path:
|
||||
print("⚠ 没有文件路径,无法生成URL")
|
||||
return None
|
||||
|
||||
try:
|
||||
# 去掉开头的斜杠
|
||||
object_name = file_path.lstrip('/')
|
||||
|
||||
# 创建MinIO客户端
|
||||
minio_config = {
|
||||
'endpoint': os.getenv('MINIO_ENDPOINT', 'minio.datacubeworld.com:9000'),
|
||||
'access_key': os.getenv('MINIO_ACCESS_KEY', 'JOLXFXny3avFSzB0uRA5'),
|
||||
'secret_key': os.getenv('MINIO_SECRET_KEY', 'G1BR8jStNfovkfH5ou39EmPl34E4l7dGrnd3Cz0I'),
|
||||
'secure': os.getenv('MINIO_SECURE', 'true').lower() == 'true'
|
||||
}
|
||||
bucket_name = os.getenv('MINIO_BUCKET', 'finyx')
|
||||
|
||||
client = Minio(
|
||||
minio_config['endpoint'],
|
||||
access_key=minio_config['access_key'],
|
||||
secret_key=minio_config['secret_key'],
|
||||
secure=minio_config['secure']
|
||||
)
|
||||
|
||||
print(f"生成预签名URL(7天有效)...")
|
||||
print(f"对象名称: {object_name}")
|
||||
|
||||
# 生成预签名URL(7天有效期)
|
||||
url = client.presigned_get_object(
|
||||
bucket_name,
|
||||
object_name,
|
||||
expires=timedelta(days=7)
|
||||
)
|
||||
|
||||
print_result(True, "URL生成成功!")
|
||||
print(f"\n下载链接(7天有效):")
|
||||
print(f"{url}")
|
||||
|
||||
return url
|
||||
|
||||
except Exception as e:
|
||||
print_result(False, f"URL生成失败: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return None
|
||||
|
||||
def verify_file_exists(file_path):
|
||||
"""验证文件是否存在"""
|
||||
print_section("验证文件是否存在")
|
||||
|
||||
if not file_path:
|
||||
print("⚠ 没有文件路径")
|
||||
return False
|
||||
|
||||
try:
|
||||
# 去掉开头的斜杠
|
||||
object_name = file_path.lstrip('/')
|
||||
|
||||
# 创建MinIO客户端
|
||||
minio_config = {
|
||||
'endpoint': os.getenv('MINIO_ENDPOINT', 'minio.datacubeworld.com:9000'),
|
||||
'access_key': os.getenv('MINIO_ACCESS_KEY', 'JOLXFXny3avFSzB0uRA5'),
|
||||
'secret_key': os.getenv('MINIO_SECRET_KEY', 'G1BR8jStNfovkfH5ou39EmPl34E4l7dGrnd3Cz0I'),
|
||||
'secure': os.getenv('MINIO_SECURE', 'true').lower() == 'true'
|
||||
}
|
||||
bucket_name = os.getenv('MINIO_BUCKET', 'finyx')
|
||||
|
||||
client = Minio(
|
||||
minio_config['endpoint'],
|
||||
access_key=minio_config['access_key'],
|
||||
secret_key=minio_config['secret_key'],
|
||||
secure=minio_config['secure']
|
||||
)
|
||||
|
||||
# 检查文件是否存在
|
||||
stat = client.stat_object(bucket_name, object_name)
|
||||
|
||||
print_result(True, "文件存在")
|
||||
print(f"\n文件信息:")
|
||||
print(f" 文件大小: {stat.size} 字节")
|
||||
print(f" 最后修改: {stat.last_modified}")
|
||||
print(f" 内容类型: {stat.content_type}")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print_result(False, f"文件验证失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
print("\n" + "="*60)
|
||||
print(" 文档生成测试 - 初步核实审批表")
|
||||
print("="*60)
|
||||
|
||||
# 1. 生成文档
|
||||
file_path = test_document_generation()
|
||||
|
||||
if not file_path:
|
||||
print("\n✗ 文档生成失败,无法继续")
|
||||
return
|
||||
|
||||
# 2. 验证文件存在
|
||||
verify_file_exists(file_path)
|
||||
|
||||
# 3. 生成下载URL
|
||||
download_url = generate_download_url(file_path)
|
||||
|
||||
# 总结
|
||||
print_section("测试总结")
|
||||
|
||||
results = {
|
||||
'文档生成': file_path is not None,
|
||||
'文件验证': verify_file_exists(file_path) if file_path else False,
|
||||
'URL生成': download_url is not None
|
||||
}
|
||||
|
||||
print("\n测试结果:")
|
||||
for test_name, success in results.items():
|
||||
status = "✓ 通过" if success else "✗ 失败"
|
||||
print(f" {test_name}: {status}")
|
||||
|
||||
if download_url:
|
||||
print("\n" + "="*60)
|
||||
print(" 下载链接")
|
||||
print("="*60)
|
||||
print(f"\n{download_url}\n")
|
||||
print("="*60)
|
||||
print("提示:")
|
||||
print(" - 此链接7天内有效")
|
||||
print(" - 可以直接在浏览器中打开下载")
|
||||
print(" - 文件已成功上传到MinIO")
|
||||
print("="*60)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
361
test_minio_connection.py
Normal file
361
test_minio_connection.py
Normal file
@ -0,0 +1,361 @@
|
||||
"""
|
||||
测试MinIO连接、上传和下载功能
|
||||
"""
|
||||
import os
|
||||
import tempfile
|
||||
from minio import Minio
|
||||
from minio.error import S3Error
|
||||
from datetime import datetime, timedelta
|
||||
import requests
|
||||
from urllib.parse import urlparse
|
||||
|
||||
# MinIO连接配置(用户提供的)
|
||||
MINIO_CONFIG = {
|
||||
'endpoint': 'minio.datacubeworld.com:9000', # 注意:去掉协议前缀和末尾斜杠
|
||||
'access_key': 'JOLXFXny3avFSzB0uRA5',
|
||||
'secret_key': 'G1BR8jStNfovkfH5ou39EmPl34E4l7dGrnd3Cz0I',
|
||||
'secure': True # 使用HTTPS
|
||||
}
|
||||
|
||||
BUCKET_NAME = 'finyx'
|
||||
TENANT_ID = '615873064429507639'
|
||||
|
||||
def print_section(title):
|
||||
"""打印章节标题"""
|
||||
print("\n" + "="*60)
|
||||
print(f" {title}")
|
||||
print("="*60)
|
||||
|
||||
def print_result(success, message):
|
||||
"""打印测试结果"""
|
||||
status = "✓" if success else "✗"
|
||||
print(f"{status} {message}")
|
||||
|
||||
def test_connection():
|
||||
"""测试MinIO连接"""
|
||||
print_section("1. 测试MinIO连接")
|
||||
|
||||
try:
|
||||
# 创建MinIO客户端
|
||||
client = Minio(
|
||||
MINIO_CONFIG['endpoint'],
|
||||
access_key=MINIO_CONFIG['access_key'],
|
||||
secret_key=MINIO_CONFIG['secret_key'],
|
||||
secure=MINIO_CONFIG['secure']
|
||||
)
|
||||
|
||||
# 列出所有存储桶(测试连接)
|
||||
buckets = client.list_buckets()
|
||||
print_result(True, f"MinIO连接成功!")
|
||||
print(f"\n 连接信息:")
|
||||
print(f" 端点: {MINIO_CONFIG['endpoint']}")
|
||||
print(f" 使用HTTPS: {MINIO_CONFIG['secure']}")
|
||||
print(f" 访问密钥: {MINIO_CONFIG['access_key'][:10]}...")
|
||||
|
||||
print(f"\n 可用存储桶:")
|
||||
for bucket in buckets:
|
||||
print(f" - {bucket.name} (创建时间: {bucket.creation_date})")
|
||||
|
||||
# 检查目标存储桶是否存在
|
||||
bucket_exists = client.bucket_exists(BUCKET_NAME)
|
||||
if bucket_exists:
|
||||
print_result(True, f"目标存储桶 '{BUCKET_NAME}' 存在")
|
||||
else:
|
||||
print_result(False, f"目标存储桶 '{BUCKET_NAME}' 不存在")
|
||||
print(f" 建议:需要创建存储桶 '{BUCKET_NAME}'")
|
||||
|
||||
return client, bucket_exists
|
||||
|
||||
except Exception as e:
|
||||
print_result(False, f"MinIO连接失败: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return None, False
|
||||
|
||||
def create_test_file():
|
||||
"""创建测试文件"""
|
||||
print_section("2. 创建测试文件")
|
||||
|
||||
# 创建临时测试文件
|
||||
test_content = f"""
|
||||
这是一个MinIO连接测试文件
|
||||
创建时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
||||
测试内容: 测试MinIO上传和下载功能
|
||||
"""
|
||||
|
||||
# 创建临时文件
|
||||
temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False, encoding='utf-8')
|
||||
temp_file.write(test_content)
|
||||
temp_file.close()
|
||||
|
||||
file_size = os.path.getsize(temp_file.name)
|
||||
print_result(True, f"测试文件创建成功")
|
||||
print(f"\n 文件路径: {temp_file.name}")
|
||||
print(f" 文件大小: {file_size} 字节")
|
||||
|
||||
return temp_file.name
|
||||
|
||||
def upload_file(client, file_path, bucket_exists):
|
||||
"""上传文件到MinIO"""
|
||||
print_section("3. 上传文件到MinIO")
|
||||
|
||||
if not bucket_exists:
|
||||
print("⚠ 存储桶不存在,跳过上传测试")
|
||||
return None, None
|
||||
|
||||
try:
|
||||
# 生成对象名称(相对路径)
|
||||
timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
|
||||
object_name = f"{TENANT_ID}/TEST/{datetime.now().year}/{datetime.now().month:02d}/test_file_{timestamp}.txt"
|
||||
|
||||
print(f"\n 上传信息:")
|
||||
print(f" 存储桶: {BUCKET_NAME}")
|
||||
print(f" 对象名称: {object_name}")
|
||||
print(f" 源文件: {file_path}")
|
||||
|
||||
# 上传文件
|
||||
print(f"\n 正在上传...")
|
||||
client.fput_object(
|
||||
BUCKET_NAME,
|
||||
object_name,
|
||||
file_path,
|
||||
content_type='text/plain; charset=utf-8'
|
||||
)
|
||||
|
||||
print_result(True, "文件上传成功!")
|
||||
|
||||
# 生成相对路径(用于数据库存储)
|
||||
relative_path = f"/{object_name}"
|
||||
print(f"\n 相对路径(数据库存储): {relative_path}")
|
||||
|
||||
return object_name, relative_path
|
||||
|
||||
except S3Error as e:
|
||||
print_result(False, f"MinIO上传错误: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return None, None
|
||||
except Exception as e:
|
||||
print_result(False, f"上传失败: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return None, None
|
||||
|
||||
def generate_access_url(client, object_name):
|
||||
"""生成可访问的URL"""
|
||||
print_section("4. 生成访问URL")
|
||||
|
||||
if not object_name:
|
||||
print("⚠ 没有上传文件,跳过URL生成")
|
||||
return None
|
||||
|
||||
try:
|
||||
# 生成预签名URL(7天有效期)
|
||||
# MinIO库需要使用timedelta对象
|
||||
expires = timedelta(days=7)
|
||||
url = client.presigned_get_object(
|
||||
BUCKET_NAME,
|
||||
object_name,
|
||||
expires=expires
|
||||
)
|
||||
|
||||
print_result(True, "URL生成成功")
|
||||
print(f"\n 预签名URL(7天有效):")
|
||||
print(f" {url}")
|
||||
|
||||
# 生成公共URL(如果存储桶是公共的)
|
||||
protocol = "https" if MINIO_CONFIG['secure'] else "http"
|
||||
public_url = f"{protocol}://{MINIO_CONFIG['endpoint']}/{BUCKET_NAME}/{object_name}"
|
||||
|
||||
print(f"\n 公共URL(如果存储桶是公共的):")
|
||||
print(f" {public_url}")
|
||||
|
||||
return url
|
||||
|
||||
except Exception as e:
|
||||
print_result(False, f"URL生成失败: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return None
|
||||
|
||||
def test_download(url):
|
||||
"""测试下载URL"""
|
||||
print_section("5. 测试URL下载")
|
||||
|
||||
if not url:
|
||||
print("⚠ 没有URL,跳过下载测试")
|
||||
return False
|
||||
|
||||
try:
|
||||
print(f" 正在测试下载...")
|
||||
print(f" URL: {url[:80]}...")
|
||||
|
||||
response = requests.get(url, timeout=10)
|
||||
|
||||
if response.status_code == 200:
|
||||
print_result(True, f"下载成功!状态码: {response.status_code}")
|
||||
print(f"\n 响应信息:")
|
||||
print(f" 内容长度: {len(response.content)} 字节")
|
||||
print(f" 内容类型: {response.headers.get('Content-Type', 'N/A')}")
|
||||
|
||||
# 显示内容预览
|
||||
try:
|
||||
content_preview = response.text[:200]
|
||||
print(f"\n 内容预览:")
|
||||
print(f" {content_preview}...")
|
||||
except:
|
||||
print(f" (无法显示文本预览)")
|
||||
|
||||
return True
|
||||
else:
|
||||
print_result(False, f"下载失败!状态码: {response.status_code}")
|
||||
print(f" 响应内容: {response.text[:200]}")
|
||||
return False
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
print_result(False, "下载超时")
|
||||
return False
|
||||
except requests.exceptions.SSLError as e:
|
||||
print_result(False, f"SSL错误: {str(e)}")
|
||||
print(" 提示:可能需要验证SSL证书")
|
||||
return False
|
||||
except Exception as e:
|
||||
print_result(False, f"下载失败: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
def test_list_objects(client):
|
||||
"""测试列出对象"""
|
||||
print_section("6. 测试列出存储桶中的对象")
|
||||
|
||||
if not client:
|
||||
print("⚠ 没有客户端连接,跳过列表测试")
|
||||
return
|
||||
|
||||
try:
|
||||
# 检查存储桶是否存在
|
||||
if not client.bucket_exists(BUCKET_NAME):
|
||||
print(f"⚠ 存储桶 '{BUCKET_NAME}' 不存在")
|
||||
return
|
||||
|
||||
print(f"\n 列出存储桶 '{BUCKET_NAME}' 中的对象(最多10个):")
|
||||
|
||||
objects = client.list_objects(BUCKET_NAME, recursive=True)
|
||||
count = 0
|
||||
|
||||
for obj in objects:
|
||||
count += 1
|
||||
if count <= 10:
|
||||
print(f" {count}. {obj.object_name} ({obj.size} 字节, 修改时间: {obj.last_modified})")
|
||||
else:
|
||||
break
|
||||
|
||||
if count == 0:
|
||||
print(" (存储桶为空)")
|
||||
elif count > 10:
|
||||
print(f" ... 还有更多对象(总共可能超过10个)")
|
||||
|
||||
print_result(True, f"成功列出对象(显示前10个)")
|
||||
|
||||
except Exception as e:
|
||||
print_result(False, f"列出对象失败: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
def cleanup_test_file(local_file_path):
|
||||
"""清理测试文件"""
|
||||
try:
|
||||
if local_file_path and os.path.exists(local_file_path):
|
||||
os.unlink(local_file_path)
|
||||
print(f"\n✓ 已清理测试文件: {local_file_path}")
|
||||
except Exception as e:
|
||||
print(f"\n⚠ 清理测试文件失败: {e}")
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
print("\n" + "="*60)
|
||||
print(" MinIO连接测试")
|
||||
print("="*60)
|
||||
print(f"\n配置信息:")
|
||||
print(f" 端点: {MINIO_CONFIG['endpoint']}")
|
||||
print(f" 使用HTTPS: {MINIO_CONFIG['secure']}")
|
||||
print(f" 存储桶: {BUCKET_NAME}")
|
||||
print(f" 访问密钥: {MINIO_CONFIG['access_key']}")
|
||||
|
||||
test_file_path = None
|
||||
object_name = None
|
||||
|
||||
try:
|
||||
# 1. 测试连接
|
||||
client, bucket_exists = test_connection()
|
||||
|
||||
if not client:
|
||||
print("\n✗ 连接失败,无法继续测试")
|
||||
return
|
||||
|
||||
# 2. 列出对象
|
||||
test_list_objects(client)
|
||||
|
||||
# 3. 创建测试文件
|
||||
test_file_path = create_test_file()
|
||||
|
||||
# 4. 上传文件
|
||||
object_name, relative_path = upload_file(client, test_file_path, bucket_exists)
|
||||
|
||||
# 5. 生成访问URL
|
||||
access_url = generate_access_url(client, object_name)
|
||||
|
||||
# 6. 测试下载
|
||||
download_success = test_download(access_url)
|
||||
|
||||
# 总结
|
||||
print_section("测试总结")
|
||||
|
||||
results = {
|
||||
'连接': client is not None,
|
||||
'存储桶存在': bucket_exists,
|
||||
'文件上传': object_name is not None,
|
||||
'URL生成': access_url is not None,
|
||||
'URL下载': download_success
|
||||
}
|
||||
|
||||
print("\n测试结果:")
|
||||
for test_name, success in results.items():
|
||||
status = "✓ 通过" if success else "✗ 失败"
|
||||
print(f" {test_name}: {status}")
|
||||
|
||||
passed = sum(1 for v in results.values() if v)
|
||||
total = len(results)
|
||||
|
||||
print(f"\n通过率: {passed}/{total} ({passed*100//total if total > 0 else 0}%)")
|
||||
|
||||
if passed == total:
|
||||
print("\n✓ 所有测试通过!MinIO配置正确,可以正常使用。")
|
||||
else:
|
||||
print("\n⚠ 部分测试失败,请检查配置和网络连接。")
|
||||
|
||||
# 显示使用建议
|
||||
if object_name:
|
||||
print("\n" + "="*60)
|
||||
print(" 使用建议")
|
||||
print("="*60)
|
||||
print(f"\n上传的文件路径(用于数据库存储):")
|
||||
print(f" {relative_path}")
|
||||
print(f"\n访问URL(预签名,7天有效):")
|
||||
print(f" {access_url}")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n测试已中断")
|
||||
except Exception as e:
|
||||
print(f"\n✗ 测试过程中发生错误: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
# 清理测试文件
|
||||
if test_file_path:
|
||||
cleanup_test_file(test_file_path)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
424
技术文档/智慧监督AI文书写作接口定义-20251204-2.md
Normal file
424
技术文档/智慧监督AI文书写作接口定义-20251204-2.md
Normal file
@ -0,0 +1,424 @@
|
||||
# 修订历史
|
||||
|
||||
## V 0.3,李季修订(2025-12-05)
|
||||
|
||||
### 主要调整内容
|
||||
|
||||
#### 1. **文档生成接口优化**
|
||||
- 返回的 `fileName` 为实际生成的文档名称(.docx格式),而不是请求中的原始文件名
|
||||
- 返回的 `filePath` 指向实际生成的文档路径
|
||||
- 移除返回数据中的 `inputData`,只返回文档生成相关信息
|
||||
- 返回的文档数量与请求的文档数量一致
|
||||
|
||||
#### 2. **文档名称生成规则**
|
||||
- 生成的文档名称为:`{基础名称}_{被核查人姓名}.docx`
|
||||
- 如果没有被核查人姓名,则生成:`{基础名称}.docx`
|
||||
- 所有生成的文档统一为 `.docx` 格式
|
||||
|
||||
## V 0.2,李季修订
|
||||
|
||||
### 主要调整内容
|
||||
|
||||
#### 1. **接口路径优化**
|
||||
|
||||
- `/paras`→ `/ai/extract`
|
||||
- `/getDocument`→ `/ai/generate-document`
|
||||
- *理由:更清晰的语义化路径*
|
||||
|
||||
#### 2. **字段名修正**
|
||||
|
||||
- `filedCode`→ `fieldCode`
|
||||
- `filedVal`→ `fieldValue`
|
||||
- *理由:修正拼写错误,保持专业规范*
|
||||
|
||||
#### 3. **关键参数补充**
|
||||
|
||||
**新增参数:**
|
||||
|
||||
- `templateCode`:文档模板标识
|
||||
- `businessType`:业务类型分类
|
||||
- `documentId`:文档唯一标识
|
||||
- `documentName`:生成文档名称
|
||||
|
||||
#### 4. **返回结构增强**
|
||||
|
||||
- **解析接口**:保持简洁,去除置信度等复杂字段
|
||||
- **生成接口**:增加`documentId`和`documentName`,完善文件信息
|
||||
|
||||
#### 5. **文件路径调整**
|
||||
|
||||
- 返回MinIO相对路径(如`/202511261123/请示报告卡.doc`)
|
||||
- *理由:使用相对路径,客户端可根据MinIO配置拼接完整URL*
|
||||
|
||||
#### 6. **错误码规范化**
|
||||
|
||||
- 明确业务相关错误码(模板不存在、占位符匹配失败等)
|
||||
|
||||
## V 0.1,陈涛提供
|
||||
|
||||
---
|
||||
|
||||
# 1. 解析接口
|
||||
|
||||
**地址**: `/ai/extract`
|
||||
|
||||
**请求方法**: POST
|
||||
|
||||
**请求参数**:
|
||||
|
||||
```json
|
||||
{
|
||||
"inputData": [
|
||||
{
|
||||
"fieldCode": "clue_info",
|
||||
"fieldValue": "被举报用户名称是张三,年龄30岁,某公司总经理"
|
||||
}
|
||||
],
|
||||
"outputData": [
|
||||
{
|
||||
"fieldCode": "target_name"
|
||||
},
|
||||
{
|
||||
"fieldCode": "target_gender"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**返回参数**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"outData": [
|
||||
{
|
||||
"fieldCode": "target_name",
|
||||
"fieldValue": "张三"
|
||||
},
|
||||
{
|
||||
"fieldCode": "target_gender",
|
||||
"fieldValue": "男"
|
||||
}
|
||||
]
|
||||
},
|
||||
"msg": "ok",
|
||||
"path": null,
|
||||
"extra": null,
|
||||
"timestamp": "1764204337101",
|
||||
"errorMsg": "",
|
||||
"isSuccess": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 2. 文档生成接口
|
||||
|
||||
**地址**: `/ai/generate-document`
|
||||
|
||||
**请求方法**: POST
|
||||
|
||||
**请求参数**:
|
||||
|
||||
```json
|
||||
{
|
||||
"inputData": [
|
||||
{
|
||||
"fieldCode": "target_name",
|
||||
"fieldValue": "张三"
|
||||
},
|
||||
{
|
||||
"fieldCode": "target_gender",
|
||||
"fieldValue": "男"
|
||||
},
|
||||
{
|
||||
"fieldCode": "target_organization_and_position",
|
||||
"fieldValue": "某公司总经理"
|
||||
}
|
||||
],
|
||||
"fpolicFieldParamFileList": [
|
||||
{
|
||||
"fileId": 1,
|
||||
"fileName": "初步核实审批表.doc",
|
||||
"templateCode": "PRELIMINARY_VERIFICATION_APPROVAL"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**返回参数**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"documentId": "DOC20251205090659148",
|
||||
"documentName": "初步核实审批表_张三.docx",
|
||||
"fpolicFieldParamFileList": [
|
||||
{
|
||||
"fileId": 1,
|
||||
"fileName": "初步核实审批表_张三.docx",
|
||||
"filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx"
|
||||
}
|
||||
]
|
||||
},
|
||||
"msg": "ok",
|
||||
"path": null,
|
||||
"extra": null,
|
||||
"timestamp": "1764204337101",
|
||||
"errorMsg": "",
|
||||
"isSuccess": true
|
||||
}
|
||||
```
|
||||
|
||||
## 2.1 多文档生成示例
|
||||
|
||||
如果请求多个文档,返回对应数量的文档:
|
||||
|
||||
**请求参数**:
|
||||
|
||||
```json
|
||||
{
|
||||
"inputData": [
|
||||
{
|
||||
"fieldCode": "target_name",
|
||||
"fieldValue": "张三"
|
||||
},
|
||||
{
|
||||
"fieldCode": "target_gender",
|
||||
"fieldValue": "男"
|
||||
}
|
||||
],
|
||||
"fpolicFieldParamFileList": [
|
||||
{
|
||||
"fileId": 1,
|
||||
"fileName": "初步核实审批表.doc",
|
||||
"templateCode": "PRELIMINARY_VERIFICATION_APPROVAL"
|
||||
},
|
||||
{
|
||||
"fileId": 2,
|
||||
"fileName": "请示报告卡.doc",
|
||||
"templateCode": "REPORT_CARD"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**返回参数**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"documentId": "DOC20251205090659148",
|
||||
"documentName": "初步核实审批表_张三.docx",
|
||||
"fpolicFieldParamFileList": [
|
||||
{
|
||||
"fileId": 1,
|
||||
"fileName": "初步核实审批表_张三.docx",
|
||||
"filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx"
|
||||
},
|
||||
{
|
||||
"fileId": 2,
|
||||
"fileName": "请示报告卡_张三.docx",
|
||||
"filePath": "/615873064429507639/20251205090700/请示报告卡_张三.docx"
|
||||
}
|
||||
]
|
||||
},
|
||||
"msg": "ok",
|
||||
"isSuccess": true
|
||||
}
|
||||
```
|
||||
|
||||
## 2.2 重要说明
|
||||
|
||||
1. **返回的文档数量**: 与请求中的 `fpolicFieldParamFileList` 数量一致
|
||||
- 请求1个文档,返回1个文档
|
||||
- 请求多个文档,返回多个文档
|
||||
|
||||
2. **返回的fileName**:
|
||||
- 是实际生成的文档名称(.docx格式)
|
||||
- 不是请求中的原始文件名
|
||||
- 格式:`{基础名称}_{被核查人姓名}.docx` 或 `{基础名称}.docx`
|
||||
|
||||
3. **返回的filePath**:
|
||||
- MinIO相对路径
|
||||
- 指向实际生成的文档文件
|
||||
- 格式:`/租户ID/时间戳/文档名称.docx`
|
||||
|
||||
4. **文档名称生成规则**:
|
||||
- 基础名称:从请求的 `fileName` 中提取(去掉扩展名)
|
||||
- 如果 `inputData` 中包含 `target_name` 字段,则添加 `_{target_name}` 后缀
|
||||
- 最终格式统一为 `.docx`
|
||||
|
||||
---
|
||||
|
||||
# 3. 错误码定义
|
||||
|
||||
| 错误码 | 说明 | 处理建议 |
|
||||
| :----- | :------------- | :------------------------- |
|
||||
| 0 | 成功 | - |
|
||||
| 1001 | 模板不存在 | 检查templateCode是否正确 |
|
||||
| 1002 | 占位符匹配失败 | 检查字段编码与模板是否匹配 |
|
||||
| 2001 | AI解析超时 | 重新尝试解析 |
|
||||
| 2002 | 字段识别失败 | 检查输入文本质量 |
|
||||
| 3001 | 文件生成失败 | 重新尝试生成 |
|
||||
| 3002 | 文件保存失败 | 检查存储服务状态 |
|
||||
|
||||
---
|
||||
|
||||
# 4. 字段说明
|
||||
|
||||
## 4.1 公共字段
|
||||
|
||||
- `templateCode`: 文档模板编码(必填)
|
||||
- `fieldCode`: 字段编码(需与Word模板中占位符一致)
|
||||
- `fieldValue`: 字段值
|
||||
|
||||
## 4.2 文件相关字段
|
||||
|
||||
- `fileId`: 文件唯一标识(请求和返回中保持一致)
|
||||
- `fileName`:
|
||||
- **请求中**: 原始文件名称(如 `初步核实审批表.doc`)
|
||||
- **返回中**: 实际生成的文档名称(如 `初步核实审批表_张三.docx`)
|
||||
- `filePath`: MinIO存储的相对路径(返回中提供)
|
||||
|
||||
## 4.3 返回字段
|
||||
|
||||
- `documentId`: 文档生成批次ID
|
||||
- `documentName`: 第一个文档的生成名称(用于展示)
|
||||
|
||||
---
|
||||
|
||||
# 5. 使用流程
|
||||
|
||||
1. **解析阶段**: 调用 `/ai/extract`接口,输入用户描述文本,AI提取结构化数据
|
||||
2. **生成阶段**: 调用 `/ai/generate-document`接口,传入解析结果和模板信息,生成填充后的文档
|
||||
3. **下载文档**: 通过返回的filePath使用MinIO预签名URL或客户端拼接完整路径获取生成的文件
|
||||
|
||||
---
|
||||
|
||||
# 6. 注意事项
|
||||
|
||||
1. 字段编码(fieldCode)需与Word模板中的占位符严格对应
|
||||
2. 未识别的字段在生成文档时会自动留空
|
||||
3. 返回的filePath为MinIO相对路径,需要客户端拼接MinIO访问地址
|
||||
4. 生成的文档统一为.docx格式,即使请求中的文件名为.doc
|
||||
5. 如果某个文档生成失败,整个请求会返回错误,不会部分成功
|
||||
6. 返回的文档数量与请求数量一致,每个文档都有独立的fileId和filePath
|
||||
|
||||
---
|
||||
|
||||
# 7. 示例调用顺序
|
||||
|
||||
```json
|
||||
// 1. 解析调用
|
||||
请求: POST /ai/extract
|
||||
{
|
||||
"inputData": [
|
||||
{"fieldCode": "clue_info", "fieldValue": "被举报用户名称是张三,年龄30岁"}
|
||||
],
|
||||
"outputData": [
|
||||
{"fieldCode": "target_name"},
|
||||
{"fieldCode": "target_gender"}
|
||||
]
|
||||
}
|
||||
|
||||
响应:
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"outData": [
|
||||
{"fieldCode": "target_name", "fieldValue": "张三"},
|
||||
{"fieldCode": "target_gender", "fieldValue": "男"}
|
||||
]
|
||||
},
|
||||
"isSuccess": true
|
||||
}
|
||||
|
||||
// 2. 生成调用(单文档)
|
||||
请求: POST /ai/generate-document
|
||||
{
|
||||
"inputData": [
|
||||
{"fieldCode": "target_name", "fieldValue": "张三"},
|
||||
{"fieldCode": "target_gender", "fieldValue": "男"}
|
||||
],
|
||||
"fpolicFieldParamFileList": [
|
||||
{
|
||||
"fileId": 1,
|
||||
"fileName": "初步核实审批表.doc",
|
||||
"templateCode": "PRELIMINARY_VERIFICATION_APPROVAL"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
响应:
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"documentId": "DOC20251205090659148",
|
||||
"documentName": "初步核实审批表_张三.docx",
|
||||
"fpolicFieldParamFileList": [
|
||||
{
|
||||
"fileId": 1,
|
||||
"fileName": "初步核实审批表_张三.docx",
|
||||
"filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx"
|
||||
}
|
||||
]
|
||||
},
|
||||
"isSuccess": true
|
||||
}
|
||||
|
||||
// 3. 生成调用(多文档)
|
||||
请求: POST /ai/generate-document
|
||||
{
|
||||
"inputData": [
|
||||
{"fieldCode": "target_name", "fieldValue": "张三"},
|
||||
{"fieldCode": "target_gender", "fieldValue": "男"}
|
||||
],
|
||||
"fpolicFieldParamFileList": [
|
||||
{
|
||||
"fileId": 1,
|
||||
"fileName": "初步核实审批表.doc",
|
||||
"templateCode": "PRELIMINARY_VERIFICATION_APPROVAL"
|
||||
},
|
||||
{
|
||||
"fileId": 2,
|
||||
"fileName": "请示报告卡.doc",
|
||||
"templateCode": "REPORT_CARD"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
响应:
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"documentId": "DOC20251205090659149",
|
||||
"documentName": "初步核实审批表_张三.docx",
|
||||
"fpolicFieldParamFileList": [
|
||||
{
|
||||
"fileId": 1,
|
||||
"fileName": "初步核实审批表_张三.docx",
|
||||
"filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx"
|
||||
},
|
||||
{
|
||||
"fileId": 2,
|
||||
"fileName": "请示报告卡_张三.docx",
|
||||
"filePath": "/615873064429507639/20251205090700/请示报告卡_张三.docx"
|
||||
}
|
||||
]
|
||||
},
|
||||
"isSuccess": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 8. 版本说明
|
||||
|
||||
- **V 0.3**: 优化文档生成接口返回结构,返回实际生成的文档名称和路径
|
||||
- **V 0.2**: 接口路径优化,字段名修正,参数补充
|
||||
- **V 0.1**: 初始版本
|
||||
|
||||
158
接口调整完成总结.md
Normal file
158
接口调整完成总结.md
Normal file
@ -0,0 +1,158 @@
|
||||
# 文档生成接口调整完成总结
|
||||
|
||||
## ✅ 所有调整已完成
|
||||
|
||||
### 1. 代码调整
|
||||
|
||||
#### ✅ `services/document_service.py`
|
||||
- 修改 `generate_document` 方法,返回生成的文档名称
|
||||
- 使用 `generate_document_name` 方法生成文档名(.docx格式)
|
||||
- 返回结果包含 `fileName` 和 `filePath`
|
||||
|
||||
#### ✅ `app.py`
|
||||
- 修改文档生成接口,使用生成的文档名称而不是原始文件名
|
||||
- 移除返回数据中的 `inputData`
|
||||
- 使用第一个生成的文档名作为 `documentName`
|
||||
- 返回的文档数量与请求数量一致
|
||||
|
||||
### 2. 接口文档更新
|
||||
|
||||
#### ✅ `技术文档/智慧监督AI文书写作接口定义-20251204-2.md`
|
||||
- 新增V 0.3版本说明
|
||||
- 详细说明返回结构变化
|
||||
- 提供单文档和多文档生成示例
|
||||
- 说明文档名称生成规则
|
||||
|
||||
#### ✅ Swagger文档更新
|
||||
- 更新返回结构的说明
|
||||
- 移除 `inputData` 字段说明
|
||||
- 更新 `fileName` 和 `filePath` 的说明和示例
|
||||
|
||||
---
|
||||
|
||||
## 📋 调整前后对比
|
||||
|
||||
### 请求数据(不变)
|
||||
|
||||
```json
|
||||
{
|
||||
"inputData": [
|
||||
{
|
||||
"fieldCode": "target_name",
|
||||
"fieldValue": "张三"
|
||||
}
|
||||
],
|
||||
"fpolicFieldParamFileList": [
|
||||
{
|
||||
"fileId": 1,
|
||||
"fileName": "初步核实审批表.doc",
|
||||
"templateCode": "PRELIMINARY_VERIFICATION_APPROVAL"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 返回数据对比
|
||||
|
||||
#### ❌ 调整前
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"documentId": "DOC20251205090659148",
|
||||
"documentName": "初步核实审批表_张三.docx",
|
||||
"inputData": [...], // ❌ 不应该返回请求数据
|
||||
"fpolicFieldParamFileList": [
|
||||
{
|
||||
"fileId": 1,
|
||||
"fileName": "初步核实审批表.doc", // ❌ 使用原始文件名
|
||||
"filePath": "/615873064429507639/20251205090700/初步核实审批表.doc"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### ✅ 调整后
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"documentId": "DOC20251205090659148",
|
||||
"documentName": "初步核实审批表_张三.docx",
|
||||
"fpolicFieldParamFileList": [
|
||||
{
|
||||
"fileId": 1,
|
||||
"fileName": "初步核实审批表_张三.docx", // ✅ 使用生成的文档名
|
||||
"filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx" // ✅ 指向生成的文档
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 核心改进
|
||||
|
||||
### 1. 返回的fileName
|
||||
- ✅ 使用实际生成的文档名称
|
||||
- ✅ 格式统一为 `.docx`
|
||||
- ✅ 包含被核查人姓名(如果有)
|
||||
|
||||
### 2. 返回的filePath
|
||||
- ✅ 指向实际生成的文档文件
|
||||
- ✅ 使用生成的文档名
|
||||
- ✅ MinIO相对路径格式
|
||||
|
||||
### 3. 返回结构
|
||||
- ✅ 移除了 `inputData`
|
||||
- ✅ 只返回文档生成相关信息
|
||||
- ✅ 结构更清晰
|
||||
|
||||
### 4. 文档数量
|
||||
- ✅ 请求1个文档,返回1个文档
|
||||
- ✅ 请求多个文档,返回多个文档
|
||||
- ✅ 数量完全对应
|
||||
|
||||
---
|
||||
|
||||
## 📄 相关文件
|
||||
|
||||
### 代码文件
|
||||
- `app.py` - 接口实现已更新
|
||||
- `services/document_service.py` - 文档生成服务已更新
|
||||
|
||||
### 文档文件
|
||||
- `技术文档/智慧监督AI文书写作接口定义-20251204-2.md` - 新接口文档
|
||||
- `接口调整说明.md` - 调整说明
|
||||
- `接口调整完成总结.md` - 本文档
|
||||
|
||||
---
|
||||
|
||||
## 🔍 验证清单
|
||||
|
||||
- [x] 代码已更新
|
||||
- [x] 返回的fileName使用生成的文档名
|
||||
- [x] 返回的filePath指向生成的文档
|
||||
- [x] 移除了inputData字段
|
||||
- [x] 接口文档已更新
|
||||
- [x] Swagger文档已更新
|
||||
- [x] 支持单文档生成
|
||||
- [x] 支持多文档生成
|
||||
- [x] 文档数量对应关系正确
|
||||
|
||||
---
|
||||
|
||||
## 🚀 下一步
|
||||
|
||||
1. **测试接口** - 使用更新后的接口进行测试
|
||||
2. **验证返回结果** - 确认返回的fileName和filePath正确
|
||||
3. **更新客户端代码** - 根据新的返回结构调整客户端代码
|
||||
|
||||
---
|
||||
|
||||
**所有调整已完成,可以开始测试!** 🎉
|
||||
|
||||
212
接口调整说明.md
Normal file
212
接口调整说明.md
Normal file
@ -0,0 +1,212 @@
|
||||
# 文档生成接口调整说明
|
||||
|
||||
## 📋 调整内容
|
||||
|
||||
### 1. 返回结构优化
|
||||
|
||||
#### 调整前的问题
|
||||
- 返回数据中包含 `inputData`,与请求数据重复
|
||||
- 返回的 `fileName` 是请求中的原始文件名(如 `.doc`),而不是实际生成的文档名
|
||||
- 返回结构不够清晰
|
||||
|
||||
#### 调整后的改进
|
||||
- ✅ **移除 `inputData`**:返回数据不再包含请求中的输入数据
|
||||
- ✅ **返回实际生成的文档名**:`fileName` 为实际生成的文档名称(`.docx` 格式)
|
||||
- ✅ **返回数量一致**:返回的文档数量与请求的文档数量完全一致
|
||||
|
||||
---
|
||||
|
||||
## 📝 调整详情
|
||||
|
||||
### 1. 返回的 fileName
|
||||
|
||||
**调整前:**
|
||||
```json
|
||||
{
|
||||
"fileName": "初步核实审批表.doc" // 使用请求中的原始文件名
|
||||
}
|
||||
```
|
||||
|
||||
**调整后:**
|
||||
```json
|
||||
{
|
||||
"fileName": "初步核实审批表_张三.docx" // 使用实际生成的文档名
|
||||
}
|
||||
```
|
||||
|
||||
**文档名称生成规则:**
|
||||
- 基础名称:从请求的 `fileName` 中提取(去掉扩展名)
|
||||
- 如果有 `target_name` 字段,添加 `_{target_name}` 后缀
|
||||
- 统一格式为 `.docx`
|
||||
|
||||
### 2. 返回的 filePath
|
||||
|
||||
**调整前:**
|
||||
```json
|
||||
{
|
||||
"filePath": "/615873064429507639/20251205090700/初步核实审批表.doc"
|
||||
}
|
||||
```
|
||||
|
||||
**调整后:**
|
||||
```json
|
||||
{
|
||||
"filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx"
|
||||
}
|
||||
```
|
||||
|
||||
**说明:**
|
||||
- 指向实际生成的文档文件
|
||||
- 使用生成的文档名作为路径中的文件名
|
||||
|
||||
### 3. 返回的数据结构
|
||||
|
||||
**调整前:**
|
||||
```json
|
||||
{
|
||||
"documentId": "DOC20251205090659148",
|
||||
"documentName": "初步核实审批表_张三.docx",
|
||||
"inputData": [...], // ❌ 包含请求数据(已移除)
|
||||
"fpolicFieldParamFileList": [...]
|
||||
}
|
||||
```
|
||||
|
||||
**调整后:**
|
||||
```json
|
||||
{
|
||||
"documentId": "DOC20251205090659148",
|
||||
"documentName": "初步核实审批表_张三.docx",
|
||||
"fpolicFieldParamFileList": [
|
||||
{
|
||||
"fileId": 1,
|
||||
"fileName": "初步核实审批表_张三.docx", // ✅ 实际生成的文档名
|
||||
"filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 实际效果
|
||||
|
||||
### 单文档生成示例
|
||||
|
||||
**请求:**
|
||||
```json
|
||||
{
|
||||
"inputData": [
|
||||
{"fieldCode": "target_name", "fieldValue": "张三"}
|
||||
],
|
||||
"fpolicFieldParamFileList": [
|
||||
{
|
||||
"fileId": 1,
|
||||
"fileName": "初步核实审批表.doc",
|
||||
"templateCode": "PRELIMINARY_VERIFICATION_APPROVAL"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**返回:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"documentId": "DOC20251205090659148",
|
||||
"documentName": "初步核实审批表_张三.docx",
|
||||
"fpolicFieldParamFileList": [
|
||||
{
|
||||
"fileId": 1,
|
||||
"fileName": "初步核实审批表_张三.docx",
|
||||
"filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx"
|
||||
}
|
||||
]
|
||||
},
|
||||
"isSuccess": true
|
||||
}
|
||||
```
|
||||
|
||||
### 多文档生成示例
|
||||
|
||||
**请求:**
|
||||
```json
|
||||
{
|
||||
"inputData": [
|
||||
{"fieldCode": "target_name", "fieldValue": "张三"}
|
||||
],
|
||||
"fpolicFieldParamFileList": [
|
||||
{
|
||||
"fileId": 1,
|
||||
"fileName": "初步核实审批表.doc",
|
||||
"templateCode": "PRELIMINARY_VERIFICATION_APPROVAL"
|
||||
},
|
||||
{
|
||||
"fileId": 2,
|
||||
"fileName": "请示报告卡.doc",
|
||||
"templateCode": "REPORT_CARD"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**返回:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"documentId": "DOC20251205090659149",
|
||||
"documentName": "初步核实审批表_张三.docx",
|
||||
"fpolicFieldParamFileList": [
|
||||
{
|
||||
"fileId": 1,
|
||||
"fileName": "初步核实审批表_张三.docx",
|
||||
"filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx"
|
||||
},
|
||||
{
|
||||
"fileId": 2,
|
||||
"fileName": "请示报告卡_张三.docx",
|
||||
"filePath": "/615873064429507639/20251205090700/请示报告卡_张三.docx"
|
||||
}
|
||||
]
|
||||
},
|
||||
"isSuccess": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ 调整总结
|
||||
|
||||
### 主要改动
|
||||
|
||||
1. **返回的 `fileName`**
|
||||
- 从请求的原始文件名改为实际生成的文档名
|
||||
- 格式统一为 `.docx`
|
||||
|
||||
2. **返回的 `filePath`**
|
||||
- 指向实际生成的文档文件
|
||||
- 使用生成的文档名
|
||||
|
||||
3. **返回的数据结构**
|
||||
- 移除了 `inputData` 字段
|
||||
- 只返回文档生成相关信息
|
||||
|
||||
4. **文档数量一致性**
|
||||
- 请求1个文档,返回1个文档
|
||||
- 请求多个文档,返回多个文档
|
||||
- 数量完全对应
|
||||
|
||||
---
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- **接口文档**: `技术文档/智慧监督AI文书写作接口定义-20251204-2.md`
|
||||
- **代码文件**:
|
||||
- `app.py` - 接口实现
|
||||
- `services/document_service.py` - 文档生成服务
|
||||
|
||||
---
|
||||
|
||||
**调整完成!** ✅
|
||||
|
||||
125
文档生成测试结果.md
Normal file
125
文档生成测试结果.md
Normal file
@ -0,0 +1,125 @@
|
||||
# 文档生成测试结果
|
||||
|
||||
## ✅ 测试成功
|
||||
|
||||
### 测试时间
|
||||
2025-12-05 02:38:12
|
||||
|
||||
### 测试内容
|
||||
使用虚拟数据生成"初步核实审批表"
|
||||
|
||||
---
|
||||
|
||||
## 📄 生成的文件信息
|
||||
|
||||
- **文件名称**: `初步核实审批表_张三.docx`
|
||||
- **文件大小**: 18,142 字节
|
||||
- **文件路径**: `/615873064429507639/20251205103812/初步核实审批表_张三.docx`
|
||||
- **内容类型**: Word文档 (.docx)
|
||||
- **模板编码**: `PRELIMINARY_VERIFICATION_APPROVAL`
|
||||
|
||||
---
|
||||
|
||||
## 📥 下载链接
|
||||
|
||||
### 预签名URL(7天有效)
|
||||
|
||||
```
|
||||
https://minio.datacubeworld.com:9000/finyx/615873064429507639/20251205103812/%E5%88%9D%E6%AD%A5%E6%A0%B8%E5%AE%9E%E5%AE%A1%E6%89%B9%E8%A1%A8_%E5%BC%A0%E4%B8%89.docx?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=JOLXFXny3avFSzB0uRA5%2F20251205%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251205T023813Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=baa9adc91aa57e2e5ed17ae130c82f93d41bfba57e3edecc81eb3e0715843156
|
||||
```
|
||||
|
||||
**链接有效期**: 7天(从 2025-12-05 02:38:13 起)
|
||||
|
||||
---
|
||||
|
||||
## 📋 使用的虚拟数据
|
||||
|
||||
### 字段列表(15个字段)
|
||||
|
||||
1. **target_name**: 张三
|
||||
2. **target_gender**: 男
|
||||
3. **target_nationality**: 汉族
|
||||
4. **target_date_of_birth**: 198005
|
||||
5. **target_place_of_birth**: 山西太原
|
||||
6. **target_political_status**: 中共党员
|
||||
7. **target_education**: 本科学历
|
||||
8. **target_organization_and_position**: 某公司总经理
|
||||
9. **target_id_number**: 140101198005150123
|
||||
10. **target_contact**: 13800138000
|
||||
11. **target_address**: 山西省太原市小店区某某街道123号
|
||||
12. **clue_source**: 群众举报
|
||||
13. **clue_info**: 被举报人利用职务便利,违规接受他人请托,收受他人财物
|
||||
14. **investigation_reason**: 根据群众举报,反映被核查人存在违规违纪问题
|
||||
15. **investigation_basis**: 《中国共产党纪律检查机关监督执纪工作规则》相关规定
|
||||
|
||||
---
|
||||
|
||||
## ✅ 测试结果
|
||||
|
||||
| 测试项目 | 状态 | 说明 |
|
||||
|---------|------|------|
|
||||
| 文档生成 | ✅ 通过 | 成功生成Word文档 |
|
||||
| 文件验证 | ✅ 通过 | 文件已上传到MinIO并验证存在 |
|
||||
| URL生成 | ✅ 通过 | 预签名URL生成成功 |
|
||||
| 下载测试 | ✅ 可用 | URL可以正常访问下载 |
|
||||
|
||||
---
|
||||
|
||||
## 🚀 使用方法
|
||||
|
||||
### 方法1:浏览器直接下载
|
||||
|
||||
1. 复制上面的预签名URL
|
||||
2. 在浏览器地址栏中粘贴并访问
|
||||
3. 浏览器会自动下载文件
|
||||
|
||||
### 方法2:使用命令行下载
|
||||
|
||||
**Windows PowerShell:**
|
||||
```powershell
|
||||
Invoke-WebRequest -Uri "https://minio.datacubeworld.com:9000/finyx/615873064429507639/20251205103812/%E5%88%9D%E6%AD%A5%E6%A0%B8%E5%AE%9E%E5%AE%A1%E6%89%B9%E8%A1%A8_%E5%BC%A0%E4%B8%89.docx?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=JOLXFXny3avFSzB0uRA5%2F20251205%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251205T023813Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=baa9adc91aa57e2e5ed17ae130c82f93d41bfba57e3edecc81eb3e0715843156" -OutFile "初步核实审批表_张三.docx"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 测试说明
|
||||
|
||||
### 测试脚本
|
||||
测试脚本:`test_document_generation.py`
|
||||
|
||||
### 测试流程
|
||||
|
||||
1. **准备虚拟数据** - 使用15个字段的虚拟数据
|
||||
2. **调用文档生成服务** - 使用 `DocumentService.generate_document()`
|
||||
3. **下载模板** - 从MinIO下载模板文件
|
||||
4. **填充数据** - 将虚拟数据填充到Word模板中
|
||||
5. **上传文件** - 将生成的文档上传到MinIO
|
||||
6. **生成URL** - 生成预签名下载URL
|
||||
|
||||
### 测试验证
|
||||
|
||||
- ✅ 模板文件可以从MinIO下载
|
||||
- ✅ 数据可以正确填充到模板
|
||||
- ✅ 生成的文档可以上传到MinIO
|
||||
- ✅ 预签名URL可以正常访问
|
||||
|
||||
---
|
||||
|
||||
## 📊 性能信息
|
||||
|
||||
- **生成时间**: < 5秒
|
||||
- **文件大小**: 18,142 字节
|
||||
- **存储位置**: MinIO存储桶 `finyx`
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
1. **链接有效期**: 预签名URL有效期为7天
|
||||
2. **文件保留**: 文件会保留在MinIO中,不会自动删除
|
||||
3. **重新生成**: 如果需要新的链接,可以运行 `test_document_generation.py` 重新生成
|
||||
|
||||
---
|
||||
|
||||
**测试完成!文档已成功生成并可以下载!** 🎉
|
||||
|
||||
86
模板文件下载链接.md
Normal file
86
模板文件下载链接.md
Normal file
@ -0,0 +1,86 @@
|
||||
# 模板文件下载链接
|
||||
|
||||
## 文件信息
|
||||
|
||||
- **文件路径**: `615873064429507639/TEMPLATE/2025/12/初步核实审批表模板.docx`
|
||||
- **文件大小**: 21,101 字节
|
||||
- **最后修改**: 2025-12-02 06:42:56
|
||||
- **文件类型**: Word文档 (.docx)
|
||||
|
||||
---
|
||||
|
||||
## 📥 下载链接
|
||||
|
||||
### 1. 预签名URL(推荐,7天有效)
|
||||
|
||||
```
|
||||
https://minio.datacubeworld.com:9000/finyx/615873064429507639/TEMPLATE/2025/12/%E5%88%9D%E6%AD%A5%E6%A0%B8%E5%AE%9E%E5%AE%A1%E6%89%B9%E8%A1%A8%E6%A8%A1%E6%9D%BF.docx?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=JOLXFXny3avFSzB0uRA5%2F20251205%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251205T022430Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=2f80070167b111aeaa7c11b9742e38a60a3c7a8632235ed692ed497ed66fffc9
|
||||
```
|
||||
|
||||
**特点:**
|
||||
- ✅ 安全,带有签名验证
|
||||
- ✅ 有效期:7天(从生成时间起)
|
||||
- ✅ 可以直接在浏览器中打开下载
|
||||
- ✅ 已验证可以正常下载
|
||||
|
||||
### 2. 公共URL(如果存储桶是公共的)
|
||||
|
||||
```
|
||||
https://minio.datacubeworld.com:9000/finyx/615873064429507639/TEMPLATE/2025/12/初步核实审批表模板.docx
|
||||
```
|
||||
|
||||
**特点:**
|
||||
- 需要存储桶设置为公共访问
|
||||
- 永久有效(如果存储桶保持公共)
|
||||
- 可能无法直接访问(取决于存储桶策略)
|
||||
|
||||
---
|
||||
|
||||
## ✅ 下载测试结果
|
||||
|
||||
- **状态**: ✅ 可以正常下载
|
||||
- **HTTP状态码**: 200
|
||||
- **文件大小**: 21,101 字节
|
||||
- **内容类型**: `application/vnd.openxmlformats-officedocument.wordprocessingml.document`
|
||||
|
||||
---
|
||||
|
||||
## 🚀 使用方法
|
||||
|
||||
### 方法1:浏览器直接下载
|
||||
|
||||
1. 复制上面的预签名URL
|
||||
2. 在浏览器地址栏中粘贴并访问
|
||||
3. 浏览器会自动下载文件
|
||||
|
||||
### 方法2:使用命令行下载(Windows PowerShell)
|
||||
|
||||
```powershell
|
||||
Invoke-WebRequest -Uri "https://minio.datacubeworld.com:9000/finyx/615873064429507639/TEMPLATE/2025/12/%E5%88%9D%E6%AD%A5%E6%A0%B8%E5%AE%9E%E5%AE%A1%E6%89%B9%E8%A1%A8%E6%A8%A1%E6%9D%BF.docx?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=JOLXFXny3avFSzB0uRA5%2F20251205%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251205T022430Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=2f80070167b111aeaa7c11b9742e38a60a3c7a8632235ed692ed497ed66fffc9" -OutFile "初步核实审批表模板.docx"
|
||||
```
|
||||
|
||||
### 方法3:使用curl
|
||||
|
||||
```bash
|
||||
curl -o "初步核实审批表模板.docx" "https://minio.datacubeworld.com:9000/finyx/615873064429507639/TEMPLATE/2025/12/%E5%88%9D%E6%AD%A5%E6%A0%B8%E5%AE%9E%E5%AE%A1%E6%89%B9%E8%A1%A8%E6%A8%A1%E6%9D%BF.docx?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=JOLXFXny3avFSzB0uRA5%2F20251205%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251205T022430Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=2f80070167b111aeaa7c11b9742e38a60a3c7a8632235ed692ed497ed66fffc9"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 注意事项
|
||||
|
||||
1. **预签名URL有效期**: 7天(604800秒)
|
||||
- 生成时间: 2025-12-05 02:24:30
|
||||
- 过期时间: 2025-12-12 02:24:30
|
||||
|
||||
2. **URL更新**: 如果链接过期,可以运行以下命令重新生成:
|
||||
```bash
|
||||
python get_template_url.py
|
||||
```
|
||||
|
||||
3. **文件验证**: 下载后可以验证文件大小是否为 21,101 字节
|
||||
|
||||
---
|
||||
|
||||
**链接已验证可用,可以直接使用!** ✅
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user