ticket/wwwroot/api/ticket_attachment.dspy

51 lines
2.1 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ticket_attachment.dspy - 工单附件打开/下载I5 可见性服务端校验)
# 入参: msg_id=<消息id>, att_id=<附件id>, download=1 时以附件名下载
# 客户只能取 visibility='customer' 消息附件staff/admin 全量。
from urllib.parse import quote as _quote
from aiohttp.web_fileresponse import FileResponse
user_id = await get_user()
if not user_id:
return {"widgettype": "Message", "options": {"title": "未登录", "message": "请先登录"}}
msg_id = ((params_kw or {}).get('msg_id') or '').strip()
att_id = ((params_kw or {}).get('att_id') or '').strip()
download = ((params_kw or {}).get('download') or '').strip()
ok, res = await ticket_get_attachment_file(msg_id, att_id, user_id, await get_userorgid())
if not ok:
code, msg = res
return {"widgettype": "Message", "options": {"title": "打开失败", "message": msg}}
full_path, fname = res
fname = str(fname)
safe_name = _quote(fname)
headers = {}
if download:
headers['Content-Disposition'] = (
'attachment; filename="%s"; filename*=UTF-8\'\'%s' % (fname, safe_name))
else:
# 图片/PDF 等浏览器可直接渲染的类型内联打开
headers['Content-Disposition'] = (
'inline; filename="%s"; filename*=UTF-8\'\'%s' % (fname, safe_name))
# 文本类显式带 charset=utf-8aiohttp FileResponse 按扩展名猜 Content-Type 不附
# charsettext/plain 无 charset 时浏览器按 ISO-8859-1 解 UTF-8 → 中文乱码
# 2026-09-11 用户报障。未知扩展名的纯文本log/conf 等)也归入 text/plain 内联展示。
import mimetypes as _mt
_ctype = _mt.guess_type(fname)[0] or ''
if not _ctype:
_ext = fname.rsplit('.', 1)[-1].lower() if '.' in fname else ''
if _ext in ('txt', 'log', 'md', 'csv', 'conf', 'ini', 'yml', 'yaml',
'py', 'js', 'sh', 'sql', 'json'):
_ctype = 'text/plain'
if _ctype.startswith('text/') or _ctype in (
'application/json', 'application/javascript',
'application/xml', 'image/svg+xml'):
_ctype += '; charset=utf-8'
if _ctype:
headers['Content-Type'] = _ctype
return FileResponse(full_path, headers=headers)