Feature (canvas): Add Api for download "message" component output's file (#11772)

### What problem does this PR solve?

-Add Api for download "message" component output's file 
-Change the attachment output type check from tuple to
dictionary,because 'attachement' is not instance of tuple
-Update the message type to message_end to avoid the problem that
content does not send an error message when the message type is ans
["data"] ["content"]

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
天海蒼灆
2025-12-05 19:42:35 +08:00
committed by GitHub
parent e4e0a88053
commit 8de6b97806
2 changed files with 21 additions and 5 deletions

View File

@@ -534,10 +534,12 @@ class Canvas(Graph):
yield decorate("message", {"content": cpn_obj.output("content")}) yield decorate("message", {"content": cpn_obj.output("content")})
cite = re.search(r"\[ID:[ 0-9]+\]", cpn_obj.output("content")) cite = re.search(r"\[ID:[ 0-9]+\]", cpn_obj.output("content"))
if isinstance(cpn_obj.output("attachment"), tuple): message_end = {}
yield decorate("message", {"attachment": cpn_obj.output("attachment")}) if isinstance(cpn_obj.output("attachment"), dict):
message_end["attachment"] = cpn_obj.output("attachment")
yield decorate("message_end", {"reference": self.get_reference() if cite else None}) if cite:
message_end["reference"] = self.get_reference()
yield decorate("message_end", message_end)
while partials: while partials:
_cpn_obj = self.get_component_obj(partials[0]) _cpn_obj = self.get_component_obj(partials[0])

View File

@@ -14,7 +14,7 @@
# limitations under the License. # limitations under the License.
# #
import asyncio
import pathlib import pathlib
import re import re
from quart import request, make_response from quart import request, make_response
@@ -29,6 +29,7 @@ from api.db import FileType
from api.db.services import duplicate_name from api.db.services import duplicate_name
from api.db.services.file_service import FileService from api.db.services.file_service import FileService
from api.utils.file_utils import filename_type from api.utils.file_utils import filename_type
from api.utils.web_utils import CONTENT_TYPE_MAP
from common import settings from common import settings
from common.constants import RetCode from common.constants import RetCode
@@ -629,6 +630,19 @@ async def get(tenant_id, file_id):
except Exception as e: except Exception as e:
return server_error_response(e) return server_error_response(e)
@manager.route("/file/download/<attachment_id>", methods=["GET"]) # noqa: F821
@token_required
async def download_attachment(tenant_id,attachment_id):
try:
ext = request.args.get("ext", "markdown")
data = await asyncio.to_thread(settings.STORAGE_IMPL.get, tenant_id, attachment_id)
response = await make_response(data)
response.headers.set("Content-Type", CONTENT_TYPE_MAP.get(ext, f"application/{ext}"))
return response
except Exception as e:
return server_error_response(e)
@manager.route('/file/mv', methods=['POST']) # noqa: F821 @manager.route('/file/mv', methods=['POST']) # noqa: F821
@token_required @token_required