From 8b89447549df36aa25786c0f2ce16021919b3604 Mon Sep 17 00:00:00 2001 From: JimintheBox Date: Thu, 27 Mar 2025 11:47:35 +0900 Subject: [PATCH] Fix Custom Tool File Upload: Resolve Multiple Files Recognition and Multipart Boundary Issues (#14014) Co-authored-by: crazywoola <427733928@qq.com> --- api/core/tools/custom_tool/tool.py | 14 +++++++++++++- api/core/tools/utils/parser.py | 3 +++ docker/ssrf_proxy/squid.conf.template | 3 +++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/api/core/tools/custom_tool/tool.py b/api/core/tools/custom_tool/tool.py index 5003c1dd51..b1121fceec 100644 --- a/api/core/tools/custom_tool/tool.py +++ b/api/core/tools/custom_tool/tool.py @@ -195,7 +195,12 @@ class ApiTool(Tool): properties = body_schema.get("properties", {}) for name, property in properties.items(): if name in parameters: - if property.get("format") == "binary": + # multiple file upload: if the type is array and the items have format as binary + if property.get("type") == "array" and property.get("items", {}).get("format") == "binary": + # parameters[name] should be a list of file objects. + for f in parameters[name]: + files.append((name, (f.filename, download(f), f.mime_type))) + elif property.get("format") == "binary": f = parameters[name] files.append((name, (f.filename, download(f), f.mime_type))) elif "$ref" in property: @@ -226,6 +231,13 @@ class ApiTool(Tool): else: body = body + # if there is a file upload, remove the Content-Type header + # so that httpx can automatically generate the boundary header required for multipart/form-data. + # issue: https://github.com/langgenius/dify/issues/13684 + # reference: https://stackoverflow.com/questions/39280438/fetch-missing-boundary-in-multipart-form-data-post + if files: + headers.pop("Content-Type", None) + if method in { "get", "head", diff --git a/api/core/tools/utils/parser.py b/api/core/tools/utils/parser.py index c69fc1f825..120c1fcfea 100644 --- a/api/core/tools/utils/parser.py +++ b/api/core/tools/utils/parser.py @@ -186,6 +186,9 @@ class ApiBasedToolSchemaParser: return ToolParameter.ToolParameterType.BOOLEAN elif typ == "string": return ToolParameter.ToolParameterType.STRING + elif typ == "array": + items = parameter.get("items") or parameter.get("schema", {}).get("items") + return ToolParameter.ToolParameterType.FILES if items and items.get("format") == "binary" else None else: return None diff --git a/docker/ssrf_proxy/squid.conf.template b/docker/ssrf_proxy/squid.conf.template index 7e85e84a6f..c74c1fb67b 100644 --- a/docker/ssrf_proxy/squid.conf.template +++ b/docker/ssrf_proxy/squid.conf.template @@ -51,3 +51,6 @@ http_port ${REVERSE_PROXY_PORT} accel vhost cache_peer ${SANDBOX_HOST} parent ${SANDBOX_PORT} 0 no-query originserver acl src_all src all http_access allow src_all + +# Unless the option's size is increased, an error will occur when uploading more than two files. +client_request_buffer_max_size 100 MB \ No newline at end of file