初始化
This commit is contained in:
130
backend/file_service.py
Normal file
130
backend/file_service.py
Normal file
@@ -0,0 +1,130 @@
|
||||
"""文件对象存储服务客户端 — https://file.wg.zgitm.com
|
||||
|
||||
认证方式:一次性 Token,每次操作前获取
|
||||
系统编码:mokeetext-edit
|
||||
"""
|
||||
|
||||
import requests
|
||||
|
||||
BASE_URL = "https://file.wg.zgitm.com"
|
||||
SYSTEM_CODE = "mokeetext-edit"
|
||||
FOLDER_PATH = "/mokeetext-images/" # 图片统一存放目录
|
||||
|
||||
|
||||
def get_token(system_code: str = SYSTEM_CODE) -> str:
|
||||
"""获取一次性 Token"""
|
||||
resp = requests.post(
|
||||
f"{BASE_URL}/api/token",
|
||||
json={"systemCode": system_code},
|
||||
timeout=15,
|
||||
)
|
||||
data = resp.json()
|
||||
if data.get("code") != 200:
|
||||
raise RuntimeError(f"获取文件服务 Token 失败: {data.get('message')}")
|
||||
return data["data"]["token"]
|
||||
|
||||
|
||||
def upload_file(
|
||||
file_data: bytes,
|
||||
filename: str,
|
||||
content_type: str,
|
||||
upload_user: str = "",
|
||||
) -> dict:
|
||||
"""
|
||||
上传文件到文件服务
|
||||
|
||||
返回: {"fileId": "...", "fileName": "...", "fileSize": 123}
|
||||
"""
|
||||
token = get_token()
|
||||
|
||||
resp = requests.post(
|
||||
f"{BASE_URL}/api/upload",
|
||||
headers={"Authorization": f"Bearer {token}"},
|
||||
files={"file": (filename, file_data, content_type)},
|
||||
data={
|
||||
"folderPath": FOLDER_PATH,
|
||||
"uploadUser": upload_user,
|
||||
},
|
||||
timeout=60,
|
||||
)
|
||||
data = resp.json()
|
||||
if data.get("code") != 200:
|
||||
raise RuntimeError(f"上传文件失败: {data.get('message')}")
|
||||
return data["data"]
|
||||
|
||||
|
||||
def download_file(file_id: str) -> tuple[bytes, str, str]:
|
||||
"""
|
||||
从文件服务下载文件
|
||||
|
||||
返回: (binary_data, content_type, filename)
|
||||
"""
|
||||
token = get_token()
|
||||
|
||||
resp = requests.get(
|
||||
f"{BASE_URL}/api/download/{file_id}",
|
||||
headers={"Authorization": f"Bearer {token}"},
|
||||
timeout=30,
|
||||
)
|
||||
if resp.status_code == 404:
|
||||
raise FileNotFoundError(f"文件不存在: {file_id}")
|
||||
if resp.status_code != 200:
|
||||
try:
|
||||
err = resp.json()
|
||||
raise RuntimeError(f"下载文件失败: {err.get('message', resp.text)}")
|
||||
except ValueError:
|
||||
raise RuntimeError(f"下载文件失败: HTTP {resp.status_code}")
|
||||
|
||||
content_type = resp.headers.get("Content-Type", "application/octet-stream")
|
||||
# 从 Content-Disposition 提取文件名
|
||||
filename = file_id
|
||||
disposition = resp.headers.get("Content-Disposition", "")
|
||||
if "filename*=" in disposition:
|
||||
# filename*=UTF-8''原始文件名
|
||||
parts = disposition.split("filename*=")
|
||||
if len(parts) > 1:
|
||||
fname = parts[1].strip()
|
||||
if "''" in fname:
|
||||
filename = fname.split("''", 1)[1]
|
||||
elif 'filename="' in disposition:
|
||||
filename = disposition.split('filename="')[1].rstrip('"')
|
||||
|
||||
return resp.content, content_type, filename
|
||||
|
||||
|
||||
def delete_file(file_id: str) -> bool:
|
||||
"""删除文件服务中的文件"""
|
||||
token = get_token()
|
||||
|
||||
resp = requests.get(
|
||||
f"{BASE_URL}/api/delete/{file_id}",
|
||||
headers={"Authorization": f"Bearer {token}"},
|
||||
timeout=15,
|
||||
)
|
||||
data = resp.json()
|
||||
if data.get("code") == 404:
|
||||
return False # 文件已不存在,也算删除成功
|
||||
if data.get("code") != 200:
|
||||
raise RuntimeError(f"删除文件失败: {data.get('message')}")
|
||||
return True
|
||||
|
||||
|
||||
def ensure_folder() -> bool:
|
||||
"""确保图片存放目录存在"""
|
||||
token = get_token()
|
||||
|
||||
resp = requests.post(
|
||||
f"{BASE_URL}/api/folder/create",
|
||||
headers={"Authorization": f"Bearer {token}"},
|
||||
json={
|
||||
"folderPath": FOLDER_PATH,
|
||||
"createdBy": SYSTEM_CODE,
|
||||
},
|
||||
timeout=15,
|
||||
)
|
||||
data = resp.json()
|
||||
if data.get("code") == 400 and "已存在" in data.get("message", ""):
|
||||
return True # 文件夹已存在,没问题
|
||||
if data.get("code") != 200:
|
||||
raise RuntimeError(f"创建文件夹失败: {data.get('message')}")
|
||||
return True
|
||||
Reference in New Issue
Block a user