- 新增XCAF转换器,直接从STP到GLB保留完整装配层级 - 修复HTTP API与CLI参数不一致问题 - 修复静默吞没错误的问题,遵循快速失败原则 - 清理旧文件,整理测试文件到tests目录 - 添加URL下载支持,可直接转换远程STP文件 - 更新文档,准确描述XCAF装配保留功能 技术改进: - 使用STEPCAFControl_Reader读取带装配信息的STEP文件 - 通过RWGltf_CafWriter直接导出GLB,无需STL中间格式 - 支持CPU多线程并行三角化 - HTTP API和CLI使用完全一致的转换参数 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
99 lines
2.8 KiB
Python
99 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
工具函数
|
||
提供通用的辅助功能
|
||
"""
|
||
|
||
import os
|
||
import uuid
|
||
from typing import Optional
|
||
from datetime import datetime
|
||
from .network_helper import is_url
|
||
|
||
|
||
def generate_task_id() -> str:
|
||
"""生成唯一任务ID"""
|
||
return str(uuid.uuid4())
|
||
|
||
|
||
def validate_file_path(file_path: str, must_exist: bool = True) -> bool:
|
||
"""验证文件路径或URL"""
|
||
if not file_path:
|
||
return False
|
||
|
||
# 如果是URL,直接返回True(具体验证在网络模块中进行)
|
||
if is_url(file_path):
|
||
return True
|
||
|
||
# 本地文件路径验证逻辑保持不变
|
||
if must_exist:
|
||
return os.path.isfile(file_path)
|
||
|
||
# 检查父目录是否存在或可创建
|
||
parent_dir = os.path.dirname(file_path)
|
||
if parent_dir and not os.path.exists(parent_dir):
|
||
try:
|
||
os.makedirs(parent_dir, exist_ok=True)
|
||
return True
|
||
except Exception:
|
||
return False
|
||
|
||
return True
|
||
|
||
|
||
def get_file_extension(file_path: str) -> str:
|
||
"""获取文件扩展名(小写)"""
|
||
return os.path.splitext(file_path)[1].lower()
|
||
|
||
|
||
def is_stp_file(file_path: str) -> bool:
|
||
"""检查是否为STP文件"""
|
||
# 如果是URL,检查URL末尾的扩展名
|
||
if is_url(file_path):
|
||
return file_path.lower().endswith(('.stp', '.step'))
|
||
|
||
# 本地文件扩展名检查
|
||
ext = get_file_extension(file_path)
|
||
return ext in ['.stp', '.step']
|
||
|
||
|
||
def is_glb_file(file_path: str) -> bool:
|
||
"""检查是否为GLB文件"""
|
||
ext = get_file_extension(file_path)
|
||
return ext == '.glb'
|
||
|
||
|
||
def format_datetime(dt: Optional[datetime]) -> Optional[str]:
|
||
"""格式化日期时间"""
|
||
if dt is None:
|
||
return None
|
||
return dt.strftime("%Y-%m-%d %H:%M:%S")
|
||
|
||
|
||
def get_file_size_mb(file_path: str) -> float:
|
||
"""获取文件大小(MB)"""
|
||
if not os.path.isfile(file_path):
|
||
return 0.0
|
||
|
||
size_bytes = os.path.getsize(file_path)
|
||
return size_bytes / (1024 * 1024)
|
||
|
||
|
||
def cleanup_temp_files(base_path: str) -> None:
|
||
"""清理临时文件"""
|
||
temp_extensions = ['.tmp', '.temp', '.tmp.stl']
|
||
base_dir = os.path.dirname(base_path)
|
||
base_name = os.path.splitext(os.path.basename(base_path))[0]
|
||
|
||
if not os.path.exists(base_dir):
|
||
return
|
||
|
||
for file_name in os.listdir(base_dir):
|
||
if file_name.startswith(base_name):
|
||
for ext in temp_extensions:
|
||
if file_name.endswith(ext):
|
||
temp_file = os.path.join(base_dir, file_name)
|
||
try:
|
||
os.remove(temp_file)
|
||
except Exception as e:
|
||
raise RuntimeError(f"无法删除临时文件 {temp_file}: {str(e)}") |