在dify工作流中如何定义filename自动生成
在 Dify 工作流中实现 filename(文件名)自动生成,核心是通过「变量动态拼接」或「代码逻辑计算」,结合业务场景(如时间戳、用户信息、内容标识)生成唯一且有意义的文件名。以下是覆盖不同场景的具体实现方案,从简单拼接到底层代码定制,适配文档导出、报告生成等高频需求。
一、核心设计原则:让文件名 “可读 + 唯一”
自动生成的文件名需满足两个核心需求:
- 可读性:包含业务标识(如 “测试用例”“用户报告”),方便用户快速识别文件内容;
- 唯一性:避免重名覆盖(常用 时间戳、随机字符串、用户 ID 等作为唯一标识)。
常见的自动文件名格式示例:
- 业务标识 + 时间戳:
测试用例_20240520143025.xlsx
- 业务标识 + 用户 ID + 随机串:
用户报告_UID123_8f7d2c.pdf
- 内容关键词 + 时间戳:
登录模块测试用例_20240520.xlsx
二、方案 1:基础动态拼接(无代码,适合简单场景)
通过 Dify 内置的「变量赋值」节点,直接拼接 系统变量(如时间戳)和 业务变量(如模块名、用户输入),无需编写代码,适合大多数基础场景。
适用场景:
生成带时间戳的固定格式文件名(如 “测试用例_20240520.xlsx”“日报_20240520_张三.docx”)。
实现步骤:
添加 “变量赋值” 节点在工作流中拖入「变量赋值」节点(通常放在 “文件生成” 节点前,如代码节点、文档导出节点),用于定义动态文件名。
配置变量拼接规则
- 目标变量名:自定义一个变量名,如
dynamic_filename
(后续文件生成节点将引用此变量); - 赋值类型:选择「模板」(支持变量拼接);
- 模板内容:按 “业务标识 + 唯一标识” 格式拼接,使用 Dify 变量语法
{{ 变量名 }}
引用动态内容。
以下是不同场景的模板示例:
场景 模板内容(直接复制到 “模板” 输入框) 生成结果示例 时间戳 + 业务标识 测试用例_{{ $timestamp('YYYYMMDDHHmmss') }}.xlsx
测试用例_20240520143025.xlsx 时间戳 + 用户输入关键词 {{ variables.user_input_module }}_测试用例_{{ $timestamp('YYYYMMDD') }}.xlsx
登录模块_测试用例_20240520.xlsx 时间戳 + 用户 ID 用户报告_UID{{ variables.user_id }}_{{ $timestamp('YYYYMMDD') }}.pdf
用户报告_UID123_20240520.pdf 关键变量说明:
{{ $timestamp('YYYYMMDDHHmmss') }}
:Dify 内置时间戳函数,支持自定义格式(YYYY
= 年,MM
= 月,DD
= 日,HH
= 时,mm
= 分,ss
= 秒);{{ variables.user_input_module }}
:业务变量(需提前定义,如用户输入的 “模块名”);{{ variables.user_id }}
:用户标识变量(如从登录态或请求参数中获取)。
- 目标变量名:自定义一个变量名,如
在文件生成节点中引用文件名后续生成文件的节点(如「代码节点」生成 Excel/PDF、「文档导出节点」),直接引用
{{ variables.dynamic_filename }}
作为文件名。示例(代码节点生成 Excel):python
运行
# 假设已生成 Excel 的 bytes 数据(excel_buffer) # 引用动态文件名 file_name = inputs.get("dynamic_filename") # 后续将文件数据与文件名关联(如返回给用户下载) return {"file_name": file_name, "file_data": base64.b64encode(excel_buffer.getvalue()).decode()}
三、方案 2:代码定制生成(适合复杂场景)
当需要更灵活的文件名规则(如根据文件内容关键词生成、随机串长度定制、多条件判断)时,使用「代码节点」编写逻辑,完全自定义文件名生成规则。
适用场景:
- 根据文档内容提取关键词作为文件名(如从测试用例中提取 “模块名”);
- 生成指定长度的随机串(如 8 位、16 位)作为唯一标识;
- 多条件分支生成不同格式的文件名(如 “VIP 用户” 和 “普通用户” 生成不同前缀)。
实现步骤:
添加 “代码节点”拖入「代码节点」,选择语言(推荐 Python,适配文件处理场景),并配置输入变量(如
content_keyword
内容关键词、user_type
用户类型)。编写文件名生成逻辑以下是不同复杂场景的代码示例:
示例 1:关键词 + 随机串 + 时间戳
python
运行
import time import random import stringdef main(content_keyword: str) -> dict:# 1. 生成唯一标识:8位随机字母数字random_str = ''.join(random.choices(string.ascii_letters + string.digits, k=8))# 2. 生成时间戳(格式:20240520)timestamp = time.strftime("%Y%m%d", time.localtime())# 3. 拼接文件名(关键词+时间戳+随机串)file_name = f"{content_keyword}_报告_{timestamp}_{random_str}.pdf"# 4. 返回文件名(供后续节点使用)return {"dynamic_filename": file_name}
生成结果:
登录功能_报告_20240520_8f7d2cA9.pdf
示例 2:多条件分支生成文件名
python
运行
import timedef main(user_type: str, module_name: str) -> dict:timestamp = time.strftime("%Y%m%dHHmmss", time.localtime())# 根据用户类型分支:VIP用户文件名带“VIP”前缀,普通用户无if user_type == "VIP":file_name = f"VIP_{module_name}_测试用例_{timestamp}.xlsx"else:file_name = f"{module_name}_测试用例_{timestamp}.xlsx"return {"dynamic_filename": file_name}
生成结果:
- VIP 用户:
VIP_支付模块_测试用例_20240520143025.xlsx
- 普通用户:
支付模块_测试用例_20240520143025.xlsx
示例 3:从内容中提取关键词生成文件名
python
运行
import timedef main(raw_content: str) -> dict:# 从原始内容中提取“模块名”(假设内容含“模块:XXX”格式)if "模块:" in raw_content:module_name = raw_content.split("模块:")[1].split("\n")[0].strip() # 提取“模块:”后的第一行内容else:module_name = "默认模块" # 默认值# 拼接文件名timestamp = time.strftime("%Y%m%d", time.localtime())file_name = f"{module_name}_文档_{timestamp}.md"return {"dynamic_filename": file_name}
输入内容:
“测试需求:模块:订单管理,功能:创建订单...”
生成结果:订单管理_文档_20240520.md
- VIP 用户:
输出变量与引用代码节点的输出变量(如
dynamic_filename
)需在节点配置中明确,后续文件生成节点直接引用此变量即可。
四、方案 3:结合知识库 / 用户输入生成(业务强关联场景)
若文件名需与知识库文档、用户输入的具体需求强关联(如 “基于需求 ID=REQ-001 生成测试用例文件”),可结合「知识库检索节点」或「用户输入变量」动态生成。
示例:基于知识库文档元数据生成文件名
- 前提:知识库文档的元数据中包含
requirement_id
(需求 ID)和module
(模块名); - 添加 “知识库检索节点”:获取目标文档的元数据(如
retrieved_doc.metadata.requirement_id
、retrieved_doc.metadata.module
); - 添加 “变量赋值” 节点:拼接文件名:
plaintext
{{ variables.retrieved_doc.metadata.module }}_测试用例_REQ{{ variables.retrieved_doc.metadata.requirement_id }}_{{ $timestamp('YYYYMMDD') }}.xlsx
- 生成结果:
订单模块_测试用例_REQ001_20240520.xlsx
五、关键注意事项
文件名合法性:避免包含 Windows/Mac 系统不允许的特殊字符(如
\ / : * ? " < > |
),可在代码中添加过滤逻辑:python
运行
# Python 过滤非法字符示例 illegal_chars = '\\/:*?"<>|' for char in illegal_chars:file_name = file_name.replace(char, "_") # 用“_”替换非法字符
变量作用域:确保用于拼接的变量(如
user_id
、module_name
)已在工作流中定义且传递到当前节点(可通过「日志」查看变量是否存在)。时间戳时区问题:Dify 内置
$timestamp()
函数默认使用 UTC 时区,若需本地时区(如东八区),建议在代码节点中用time.localtime()
(Python)或new Date().toLocaleString()
(JavaScript)处理。文件名长度限制:Windows 系统文件名最大长度为 255 个字符,拼接时需控制总长度(可通过代码截断关键词,如
module_name[:10]
取前 10 个字符)。
六、总结:如何选择方案
方案 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
基础变量拼接 | 简单格式(时间戳 + 固定标识)、无代码需求 | 快速实现,无需编程 | 灵活性低,不支持复杂逻辑 |
代码定制生成 | 复杂规则(多条件、随机串、内容提取) | 完全自定义,灵活度高 | 需基础编程能力 |
结合知识库 / 用户输入 | 业务强关联(需求 ID、模块名) | 与业务深度结合 | 依赖前置节点数据 |
日常工作中,方案 1(基础变量拼接) 能覆盖 80% 以上的简单场景;若需更灵活的规则(如内容提取、多条件分支),优先用 方案 2(代码节点);涉及知识库或用户需求关联时,用 方案 3 实现业务闭环。