# WebSocket 文件管理API文档 ## 概述 通过WebSocket连接实现CAD文件的列表查询和下载功能。支持Creo、PDMS、Revit三种CAD软件的文件格式。 ## WebSocket连接 **连接地址**: `ws://localhost:8000/api/v1/ws/connect` **连接参数**: - `client_id`: 客户端ID(可选,不提供会自动生成) - `user_id`: 用户ID(可选) **连接示例**: ```javascript const ws = new WebSocket('ws://localhost:8000/api/v1/ws/connect?user_id=user123'); ``` --- ## 支持的文件格式 ### 📐 Creo 文件 - `.prt` - 零件文件(Part) - `.asm` - 装配文件(Assembly) - `.drw` - 工程图文件(Drawing) - **特别支持版本号后缀**:`.prt.1`, `.prt.2`, `.asm.1` 等 ### 🏭 PDMS 文件 - `.rvm` - 3D模型文件 - `.dri` - 图纸文件 ### 🏗️ Revit 文件 - `.rvt` - Revit项目文件 - `.rfa` - Revit族文件(Family) - `.rte` - Revit模板文件 --- ## WebSocket消息格式 ### 1. 获取CAD文件列表 **发送消息**: ```json { "type": "get_file_list" } ``` **响应消息**: ```json { "type": "info", "message": "获取文件列表成功", "data": { "base_path": "C:\\Users\\Public\\Documents", "total_count": 15, "files": [ { "filename": "part1.prt.1", "relative_path": "creo/part1.prt.1", "absolute_path": "C:\\Users\\Public\\Documents\\creo\\part1.prt.1", "size": 1024000, "modified_time": 1706950800.0, "extension": ".prt.1" }, { "filename": "building.rvt", "relative_path": "revit/building.rvt", "absolute_path": "C:\\Users\\Public\\Documents\\revit\\building.rvt", "size": 5120000, "modified_time": 1706951000.0, "extension": ".rvt" } ] }, "timestamp": "2026-02-04T10:30:00" } ``` --- ### 2. 获取单个文件下载链接 **发送消息**: ```json { "type": "download_file", "file_path": "creo/part1.prt.1" } ``` **响应消息**: ```json { "type": "info", "message": "文件下载链接已生成", "data": { "file_path": "creo/part1.prt.1", "filename": "part1.prt.1", "download_url": "/api/v1/files/download/creo/part1.prt.1", "file_size": 1024000 }, "timestamp": "2026-02-04T10:30:00" } ``` **使用下载链接**: ```javascript // 获取到download_url后,使用HTTP GET请求下载 const downloadUrl = `http://localhost:8000${data.download_url}`; window.open(downloadUrl, '_blank'); ``` --- ### 3. 获取批量下载链接 **发送消息**: ```json { "type": "download_batch", "file_paths": [ "creo/part1.prt.1", "creo/assembly.asm", "revit/building.rvt" ] } ``` **响应消息**: ```json { "type": "info", "message": "批量下载链接已生成", "data": { "file_count": 3, "file_paths": [ "creo/part1.prt.1", "creo/assembly.asm", "revit/building.rvt" ], "download_url": "/api/v1/files/download/batch", "method": "POST", "note": "请使用POST方法,将file_paths作为JSON数组发送到此URL" }, "timestamp": "2026-02-04T10:30:00" } ``` **使用批量下载**: ```javascript // 使用fetch API进行POST请求 const response = await fetch('http://localhost:8000/api/v1/files/download/batch', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data.file_paths) }); const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'cad_files.zip'; a.click(); ``` --- ## 完整前端示例 ### JavaScript/WebSocket ```javascript class CADFileManager { constructor(serverUrl = 'ws://localhost:8000/api/v1/ws/connect') { this.ws = null; this.serverUrl = serverUrl; this.httpBaseUrl = 'http://localhost:8000'; } // 连接WebSocket connect(userId = 'user123') { return new Promise((resolve, reject) => { this.ws = new WebSocket(`${this.serverUrl}?user_id=${userId}`); this.ws.onopen = () => { console.log('WebSocket连接成功'); resolve(); }; this.ws.onerror = (error) => { console.error('WebSocket错误:', error); reject(error); }; this.ws.onmessage = (event) => { const message = JSON.parse(event.data); this.handleMessage(message); }; }); } // 处理服务器消息 handleMessage(message) { console.log('收到消息:', message); if (message.type === 'info' && message.data) { // 处理不同类型的响应 if (message.data.files) { this.onFileListReceived(message.data); } else if (message.data.download_url) { this.onDownloadUrlReceived(message.data); } } else if (message.type === 'error') { console.error('错误:', message.message); } } // 获取文件列表 getFileList() { this.ws.send(JSON.stringify({ type: 'get_file_list' })); } // 文件列表回调(可以被覆盖) onFileListReceived(data) { console.log('文件列表:', data.files); console.log('总数:', data.total_count); } // 请求单个文件下载 requestDownload(filePath) { this.ws.send(JSON.stringify({ type: 'download_file', file_path: filePath })); } // 下载URL回调 onDownloadUrlReceived(data) { const fullUrl = `${this.httpBaseUrl}${data.download_url}`; console.log('下载链接:', fullUrl); // 自动触发下载 window.open(fullUrl, '_blank'); } // 请求批量下载 async requestBatchDownload(filePaths) { // 批量下载直接使用HTTP POST const response = await fetch(`${this.httpBaseUrl}/api/v1/files/download/batch`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(filePaths) }); const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'cad_files.zip'; a.click(); window.URL.revokeObjectURL(url); } // 断开连接 disconnect() { if (this.ws) { this.ws.close(); } } } // 使用示例 async function main() { const manager = new CADFileManager(); // 连接 await manager.connect('user123'); // 自定义文件列表回调 manager.onFileListReceived = (data) => { console.log(`找到 ${data.total_count} 个文件`); data.files.forEach(file => { console.log(`- ${file.filename} (${(file.size / 1024).toFixed(2)} KB)`); }); }; // 获取文件列表 manager.getFileList(); // 下载单个文件 setTimeout(() => { manager.requestDownload('creo/part1.prt.1'); }, 2000); // 批量下载 setTimeout(async () => { await manager.requestBatchDownload([ 'creo/part1.prt.1', 'revit/building.rvt' ]); }, 4000); } main(); ``` --- ### React示例 ```jsx import React, { useState, useEffect, useRef } from 'react'; function CADFileManager() { const [files, setFiles] = useState([]); const [selectedFiles, setSelectedFiles] = useState([]); const [connected, setConnected] = useState(false); const wsRef = useRef(null); useEffect(() => { // 连接WebSocket const ws = new WebSocket('ws://localhost:8000/api/v1/ws/connect?user_id=user123'); ws.onopen = () => { console.log('WebSocket连接成功'); setConnected(true); // 连接成功后立即获取文件列表 ws.send(JSON.stringify({ type: 'get_file_list' })); }; ws.onmessage = (event) => { const message = JSON.parse(event.data); if (message.type === 'info' && message.data?.files) { setFiles(message.data.files); } else if (message.type === 'info' && message.data?.download_url) { // 自动打开下载链接 window.open(`http://localhost:8000${message.data.download_url}`, '_blank'); } }; wsRef.current = ws; return () => { ws.close(); }; }, []); // 刷新文件列表 const refreshFileList = () => { if (wsRef.current && connected) { wsRef.current.send(JSON.stringify({ type: 'get_file_list' })); } }; // 下载单个文件 const downloadFile = (filePath) => { if (wsRef.current && connected) { wsRef.current.send(JSON.stringify({ type: 'download_file', file_path: filePath })); } }; // 批量下载 const downloadBatch = async () => { const response = await fetch('http://localhost:8000/api/v1/files/download/batch', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(selectedFiles) }); const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'cad_files.zip'; a.click(); window.URL.revokeObjectURL(url); }; // 切换文件选择 const toggleFileSelection = (filePath) => { setSelectedFiles(prev => prev.includes(filePath) ? prev.filter(f => f !== filePath) : [...prev, filePath] ); }; return (

CAD文件管理器

连接状态: {connected ? '✅ 已连接' : '❌ 未连接'}

文件列表 (共 {files.length} 个)

{files.map(file => ( ))}
选择 文件名 路径 大小 扩展名 操作
toggleFileSelection(file.relative_path)} /> {file.filename} {file.relative_path} {(file.size / 1024).toFixed(2)} KB {file.extension}
); } export default CADFileManager; ``` --- ## 错误处理 **错误响应格式**: ```json { "type": "error", "message": "错误描述", "timestamp": "2026-02-04T10:30:00" } ``` **常见错误**: - `"缺少参数: file_path"` - 未提供文件路径 - `"缺少参数: file_paths (必须是数组)"` - 批量下载参数格式错误 - `"访问被拒绝"` - 文件路径不安全 - `"文件不存在"` - 请求的文件不存在 - `"只能下载CAD文件"` - 尝试下载非CAD格式文件 - `"获取文件列表失败"` - 扫描文件系统失败 --- ## 注意事项 1. **WebSocket用于控制,HTTP用于下载** - 文件列表通过WebSocket返回 - 文件下载使用HTTP接口(因为WebSocket不适合传输大文件) 2. **路径安全** - 所有文件路径都会进行安全检查 - 只能访问配置目录内的文件 3. **文件格式限制** - 只能下载Creo、PDMS、Revit格式的文件 - 自动识别带版本号的Creo文件 4. **批量下载** - 文件打包为ZIP格式 - 保持原有目录结构 - 自动跳过不存在或不安全的文件 5. **配置路径** - 默认路径:`C:\Users\Public\Documents` - 可在 `configs/software_config.yaml` 中修改 --- ## 文件批量重命名功能 ### 4. 获取重命名策略列表 **发送消息**: ```json { "type": "get_rename_strategies" } ``` **响应消息**: ```json { "type": "info", "message": "获取重命名策略成功", "data": { "strategies": [ { "name": "add_prefix", "description": "在文件名前添加前缀" }, { "name": "add_suffix", "description": "在扩展名前添加后缀" }, { "name": "sequence", "description": "使用序号重命名文件" }, { "name": "replace_text", "description": "替换文件名中的文本" }, { "name": "add_datetime", "description": "添加日期时间戳" }, { "name": "change_case", "description": "转换文件名大小写" } ], "total_count": 6 }, "timestamp": "2026-02-04T11:10:00" } ``` --- ### 5. 预览重命名结果 **发送消息**: ```json { "type": "preview_rename", "file_paths": [ "creo/part1.prt.1", "creo/assembly.asm", "revit/building.rvt" ], "strategy": "add_prefix", "params": { "prefix": "NEW_" } } ``` **响应消息**: ```json { "type": "info", "message": "重命名预览生成成功", "data": { "strategy": "add_prefix", "params": { "prefix": "NEW_" }, "preview": [ { "original": "part1.prt.1", "new": "NEW_part1.prt.1", "success": true }, { "original": "assembly.asm", "new": "NEW_assembly.asm", "success": true }, { "original": "building.rvt", "new": "NEW_building.rvt", "success": true } ], "total_count": 3 }, "timestamp": "2026-02-04T11:10:00" } ``` --- ### 6. 执行批量重命名 **发送消息**: ```json { "type": "rename_files", "file_paths": [ "creo/part1.prt.1", "creo/assembly.asm" ], "strategy": "sequence", "params": { "base_name": "component", "start_number": 1, "digits": 3, "separator": "_" } } ``` **响应消息**: ```json { "type": "info", "message": "批量重命名完成: 成功 2 个, 失败 0 个", "data": { "strategy": "sequence", "params": { "base_name": "component", "start_number": 1, "digits": 3, "separator": "_" }, "success_count": 2, "failed_count": 0, "results": [ { "original_path": "creo/part1.prt.1", "original_name": "part1.prt.1", "new_name": "component_001.prt.1", "new_path": "creo/component_001.prt.1", "success": true }, { "original_path": "creo/assembly.asm", "original_name": "assembly.asm", "new_name": "component_002.asm", "new_path": "creo/component_002.asm", "success": true } ] }, "timestamp": "2026-02-04T11:10:00" } ``` --- ## 重命名策略参数说明 ### 1. add_prefix(添加前缀) ```json { "strategy": "add_prefix", "params": { "prefix": "NEW_" } } ``` ### 2. add_suffix(添加后缀) ```json { "strategy": "add_suffix", "params": { "suffix": "_backup" } } ``` ### 3. sequence(序号重命名) ```json { "strategy": "sequence", "params": { "base_name": "file", "start_number": 1, "digits": 3, "separator": "_" } } ``` - `base_name`: 基础文件名 - `start_number`: 起始序号(默认1) - `digits`: 序号位数(默认3,如001) - `separator`: 分隔符(默认下划线) ### 4. replace_text(文本替换) ```json { "strategy": "replace_text", "params": { "search": "old", "replace": "new", "case_sensitive": true } } ``` - `search`: 要搜索的文本 - `replace`: 替换为的文本 - `case_sensitive`: 是否区分大小写(默认true) ### 5. add_datetime(添加日期时间) ```json { "strategy": "add_datetime", "params": { "format": "%Y%m%d_%H%M%S", "position": "suffix", "separator": "_" } } ``` - `format`: 日期时间格式(默认:`%Y%m%d_%H%M%S`) - `position`: 位置,`prefix`或`suffix`(默认suffix) - `separator`: 分隔符(默认下划线) ### 6. change_case(大小写转换) ```json { "strategy": "change_case", "params": { "case_type": "lower" } } ``` - `case_type`: 转换类型,可选值:`lower`(小写)、`upper`(大写)、`title`(标题格式) --- ## 重命名功能使用示例 ### JavaScript示例 ```javascript // 扩展之前的 CADFileManager 类 class CADFileManager { // ... 之前的代码 ... // 获取重命名策略列表 getRenameStrategies() { this.ws.send(JSON.stringify({ type: 'get_rename_strategies' })); } // 预览重命名 previewRename(filePaths, strategy, params) { this.ws.send(JSON.stringify({ type: 'preview_rename', file_paths: filePaths, strategy: strategy, params: params })); } // 执行批量重命名 renameFiles(filePaths, strategy, params) { this.ws.send(JSON.stringify({ type: 'rename_files', file_paths: filePaths, strategy: strategy, params: params })); } } // 使用示例 async function renameExample() { const manager = new CADFileManager(); await manager.connect('user123'); // 1. 获取策略列表 manager.getRenameStrategies(); // 2. 预览重命名(添加前缀) setTimeout(() => { manager.previewRename( ['creo/part1.prt.1', 'creo/assembly.asm'], 'add_prefix', { prefix: 'V2_' } ); }, 1000); // 3. 执行重命名(序号重命名) setTimeout(() => { manager.renameFiles( ['creo/part1.prt.1', 'creo/part2.prt.1'], 'sequence', { base_name: 'component', start_number: 1, digits: 3, separator: '_' } ); }, 3000); } ``` ### React示例 ```jsx function CADFileRenamer() { const [files, setFiles] = useState([]); const [selectedFiles, setSelectedFiles] = useState([]); const [strategies, setStrategies] = useState([]); const [selectedStrategy, setSelectedStrategy] = useState(''); const [renameParams, setRenameParams] = useState({}); const [previewResults, setPreviewResults] = useState([]); const wsRef = useRef(null); useEffect(() => { const ws = new WebSocket('ws://localhost:8000/api/v1/ws/connect?user_id=user123'); ws.onopen = () => { // 获取文件列表和策略列表 ws.send(JSON.stringify({ type: 'get_file_list' })); ws.send(JSON.stringify({ type: 'get_rename_strategies' })); }; ws.onmessage = (event) => { const message = JSON.parse(event.data); if (message.type === 'info') { if (message.data?.files) { setFiles(message.data.files); } else if (message.data?.strategies) { setStrategies(message.data.strategies); } else if (message.data?.preview) { setPreviewResults(message.data.preview); } else if (message.data?.results) { // 重命名完成,刷新文件列表 ws.send(JSON.stringify({ type: 'get_file_list' })); setPreviewResults([]); setSelectedFiles([]); } } }; wsRef.current = ws; return () => ws.close(); }, []); // 预览重命名 const handlePreview = () => { if (wsRef.current && selectedFiles.length > 0 && selectedStrategy) { wsRef.current.send(JSON.stringify({ type: 'preview_rename', file_paths: selectedFiles, strategy: selectedStrategy, params: renameParams })); } }; // 执行重命名 const handleRename = () => { if (wsRef.current && selectedFiles.length > 0 && selectedStrategy) { if (confirm(`确定要重命名 ${selectedFiles.length} 个文件吗?`)) { wsRef.current.send(JSON.stringify({ type: 'rename_files', file_paths: selectedFiles, strategy: selectedStrategy, params: renameParams })); } } }; return (

CAD文件批量重命名

{/* 策略选择 */}
{/* 参数输入(根据策略动态显示) */} {selectedStrategy === 'add_prefix' && (
setRenameParams({...renameParams, prefix: e.target.value})} />
)} {/* 操作按钮 */}
{/* 预览结果 */} {previewResults.length > 0 && (

预览结果

{previewResults.map((result, idx) => (
{result.original} → {result.new}
))}
)} {/* 文件列表 */}

文件列表

{files.map(file => ( ))}
选择 文件名 路径
{ if (e.target.checked) { setSelectedFiles([...selectedFiles, file.relative_path]); } else { setSelectedFiles(selectedFiles.filter(f => f !== file.relative_path)); } }} /> {file.filename} {file.relative_path}
); } ``` --- ## 重命名功能注意事项 1. **文件名冲突处理** - 如果重命名后的文件名已存在,系统会自动添加数字后缀(如 `file_1`, `file_2`) - 最多尝试1000次,避免无限循环 2. **扩展名保留** - 所有重命名策略都会保留原有的文件扩展名 - 支持带版本号的扩展名(如 `.prt.1`, `.prt.2`) 3. **预览功能** - 建议在执行重命名前先使用预览功能 - 预览不会修改实际文件,只返回重命名结果 4. **错误处理** - 批量重命名时,单个文件失败不会影响其他文件 - 返回结果中会详细说明每个文件的成功/失败状态 5. **安全性** - 只能重命名配置目录内的CAD文件 - 路径安全检查防止目录遍历攻击 --- ## 配置管理功能 ### 7. 获取文件配置 **发送消息**: ```json { "type": "get_file_config" } ``` **响应消息**: ```json { "type": "info", "message": "获取文件配置成功", "data": { "base_path": "C:\\Users\\Public\\Documents", "file_extensions": { "creo": [".prt", ".asm", ".drw"], "pdms": [".rvm", ".dri"], "revit": [".rvt", ".rfa", ".rte"] } }, "timestamp": "2026-02-04T14:30:00" } ``` --- ### 8. 设置文件基础路径 **发送消息**: ```json { "type": "set_base_path", "base_path": "D:\\CAD_Files" } ``` **响应消息(成功)**: ```json { "type": "info", "message": "基础路径设置成功", "data": { "base_path": "D:\\CAD_Files" }, "timestamp": "2026-02-04T14:30:00" } ``` **响应消息(失败)**: ```json { "type": "error", "message": "设置基础路径失败: 路径不存在: D:\\Invalid_Path", "timestamp": "2026-02-04T14:30:00" } ``` --- ### 9. 设置文件扩展名 **发送消息**: ```json { "type": "set_file_extensions", "file_extensions": { "creo": [".prt", ".asm", ".drw", ".sec"], "pdms": [".rvm", ".dri"], "revit": [".rvt", ".rfa", ".rte"], "autocad": [".dwg", ".dxf"] } } ``` **响应消息(成功)**: ```json { "type": "info", "message": "文件扩展名配置已更新", "data": { "file_extensions": { "creo": [".prt", ".asm", ".drw", ".sec"], "pdms": [".rvm", ".dri"], "revit": [".rvt", ".rfa", ".rte"], "autocad": [".dwg", ".dxf"] } }, "timestamp": "2026-02-04T14:30:00" } ``` **响应消息(失败)**: ```json { "type": "error", "message": "设置文件扩展名失败: 扩展名格式错误: dwg,必须以'.'开头", "timestamp": "2026-02-04T14:30:00" } ``` --- ## 配置管理功能使用示例 ### JavaScript示例 ```javascript // 扩展之前的 CADFileManager 类 class CADFileManager { // ... 之前的代码 ... // 获取文件配置 getFileConfig() { this.ws.send(JSON.stringify({ type: 'get_file_config' })); } // 设置基础路径 setBasePath(basePath) { this.ws.send(JSON.stringify({ type: 'set_base_path', base_path: basePath })); } // 设置文件扩展名 setFileExtensions(extensions) { this.ws.send(JSON.stringify({ type: 'set_file_extensions', file_extensions: extensions })); } } // 使用示例 async function configExample() { const manager = new CADFileManager(); await manager.connect('user123'); // 1. 获取当前配置 manager.getFileConfig(); // 2. 修改基础路径 setTimeout(() => { manager.setBasePath('D:\\CAD_Files'); }, 1000); // 3. 修改文件扩展名(添加AutoCAD支持) setTimeout(() => { manager.setFileExtensions({ creo: ['.prt', '.asm', '.drw'], pdms: ['.rvm', '.dri'], revit: ['.rvt', '.rfa', '.rte'], autocad: ['.dwg', '.dxf'] }); }, 2000); } ``` ### React示例 ```jsx function CADConfigManager() { const [basePath, setBasePath] = useState(''); const [fileExtensions, setFileExtensions] = useState({}); const [newBasePath, setNewBasePath] = useState(''); const wsRef = useRef(null); useEffect(() => { const ws = new WebSocket('ws://localhost:8000/api/v1/ws/connect?user_id=user123'); ws.onopen = () => { // 连接成功后获取当前配置 ws.send(JSON.stringify({ type: 'get_file_config' })); }; ws.onmessage = (event) => { const message = JSON.parse(event.data); if (message.type === 'info' && message.data) { if (message.data.base_path) { setBasePath(message.data.base_path); } if (message.data.file_extensions) { setFileExtensions(message.data.file_extensions); } } }; wsRef.current = ws; return () => ws.close(); }, []); // 修改基础路径 const handleSetBasePath = () => { if (wsRef.current && newBasePath) { wsRef.current.send(JSON.stringify({ type: 'set_base_path', base_path: newBasePath })); } }; // 修改文件扩展名 const handleSetExtensions = (software, extensions) => { const newExtensions = { ...fileExtensions, [software]: extensions }; if (wsRef.current) { wsRef.current.send(JSON.stringify({ type: 'set_file_extensions', file_extensions: newExtensions })); } }; return (

CAD配置管理器

当前基础路径

{basePath}

setNewBasePath(e.target.value)} />

当前文件扩展名配置

{JSON.stringify(fileExtensions, null, 2)}
); } ``` --- ## 配置管理功能注意事项 1. **路径验证** - 设置基础路径前会验证路径是否存在 - 路径必须是有效的目录,不能是文件 2. **扩展名格式** - 所有扩展名必须以`.`开头 - 扩展名配置必须是字典格式,值必须是数组 3. **配置持久化** - 所有配置修改会立即写入`configs/software_config.yaml`文件 - 配置修改后会立即生效,影响文件列表和下载功能 4. **权限要求** - 修改配置需要对配置文件有写入权限 - 建议在管理员权限下运行 5. **配置同步** - 修改配置后,建议重新获取文件列表以查看变更效果 - 多个客户端同时修改配置时,以最后一次修改为准