# 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 headers = {} if download: safe_name = _quote(str(fname)) 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)) return FileResponse(full_path, headers=headers)