fix(office): univer-office 端口 9091→19091,避免与 pipeline worker 1 撞端口
This commit is contained in:
parent
42f3b7bf26
commit
9f931347db
48
wwwroot/api/office_read.dspy
Normal file
48
wwwroot/api/office_read.dspy
Normal file
@ -0,0 +1,48 @@
|
||||
# office_read.dspy - 读取工作空间 docx 文件,转 markdown 返回给 univer-office 前端
|
||||
import os
|
||||
import aiohttp
|
||||
|
||||
file_id = (params_kw or {}).get('file', '').strip()
|
||||
|
||||
uid = await get_user()
|
||||
if not uid:
|
||||
uid = 'user-01'
|
||||
|
||||
dbname = get_module_dbname('pipeline-sdlc')
|
||||
|
||||
async with DBPools().sqlorContext(dbname) as sor:
|
||||
ws_dir, _ = await get_workspace_dir(sor, uid)
|
||||
|
||||
if not file_id or not ws_dir:
|
||||
return {"error": "未指定文件或无工作空间", "markdown": ""}
|
||||
|
||||
full_path = ws_dir + '/' + file_id
|
||||
|
||||
# 路径穿越校验
|
||||
real_ws = os.path.realpath(ws_dir)
|
||||
real_full = os.path.realpath(full_path)
|
||||
if not real_full.startswith(real_ws + os.sep):
|
||||
return {"error": "非法路径", "markdown": ""}
|
||||
|
||||
if not os.path.isfile(full_path):
|
||||
return {"error": "文件不存在", "markdown": ""}
|
||||
|
||||
# 读 docx bytes
|
||||
with open(full_path, 'rb') as f:
|
||||
docx_bytes = f.read()
|
||||
|
||||
# 调 univer-office 转 IDocumentData(格式保真,跳过 markdown)
|
||||
try:
|
||||
timeout = aiohttp.ClientTimeout(total=60)
|
||||
async with aiohttp.ClientSession(timeout=timeout) as session:
|
||||
async with session.post(
|
||||
'http://127.0.0.1:19091/convert/docx-to-docdata',
|
||||
data=docx_bytes,
|
||||
headers={'Content-Type': 'application/octet-stream'},
|
||||
) as resp:
|
||||
if resp.status != 200:
|
||||
return {"error": f"转换失败 HTTP {resp.status}", "documentData": None}
|
||||
doc_data = await resp.json()
|
||||
return {"documentData": doc_data}
|
||||
except Exception as e:
|
||||
return {"error": str(e), "documentData": None}
|
||||
63
wwwroot/api/office_save.dspy
Normal file
63
wwwroot/api/office_save.dspy
Normal file
@ -0,0 +1,63 @@
|
||||
# office_save.dspy - univer-office 编辑后保存:IDocumentData -> docx 写回工作空间
|
||||
import os
|
||||
import json as _json
|
||||
import aiohttp
|
||||
|
||||
file_id = (params_kw or {}).get('file', '').strip()
|
||||
docdata_str = (params_kw or {}).get('documentData', '') or ''
|
||||
|
||||
uid = await get_user()
|
||||
if not uid:
|
||||
uid = 'user-01'
|
||||
|
||||
dbname = get_module_dbname('pipeline-sdlc')
|
||||
|
||||
async with DBPools().sqlorContext(dbname) as sor:
|
||||
ws_dir, _ = await get_workspace_dir(sor, uid)
|
||||
|
||||
if not file_id or not ws_dir:
|
||||
return {"success": False, "error": "未指定文件或无工作空间"}
|
||||
|
||||
if not docdata_str:
|
||||
return {"success": False, "error": "缺少文档数据"}
|
||||
|
||||
try:
|
||||
documentData = _json.loads(docdata_str)
|
||||
except Exception as e:
|
||||
return {"success": False, "error": f"文档数据解析失败: {e}"}
|
||||
|
||||
full_path = ws_dir + '/' + file_id
|
||||
|
||||
# 路径穿越校验
|
||||
real_ws = os.path.realpath(ws_dir)
|
||||
real_full = os.path.realpath(full_path)
|
||||
if not real_full.startswith(real_ws + os.sep):
|
||||
return {"success": False, "error": "非法路径"}
|
||||
|
||||
# 只允许覆盖已存在的 office 文件(防任意写入)
|
||||
if not os.path.isfile(full_path):
|
||||
return {"success": False, "error": "目标文件不存在"}
|
||||
|
||||
title = os.path.basename(full_path)
|
||||
|
||||
# 调 univer-office 生成 docx(IDocumentData -> docx,保留格式)
|
||||
try:
|
||||
timeout = aiohttp.ClientTimeout(total=120)
|
||||
async with aiohttp.ClientSession(timeout=timeout) as session:
|
||||
async with session.post(
|
||||
'http://127.0.0.1:19091/convert/doc-data-to-docx',
|
||||
json={'documentData': documentData, 'title': title},
|
||||
) as resp:
|
||||
if resp.status != 200:
|
||||
return {"success": False, "error": f"导出失败 HTTP {resp.status}"}
|
||||
docx_bytes = await resp.read()
|
||||
except Exception as e:
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
# 写回工作空间
|
||||
try:
|
||||
with open(full_path, 'wb') as f:
|
||||
f.write(docx_bytes)
|
||||
return {"success": True, "bytes": len(docx_bytes)}
|
||||
except Exception as e:
|
||||
return {"success": False, "error": str(e)}
|
||||
Loading…
x
Reference in New Issue
Block a user