news 2026/9/6 18:49:21

ToolJet Generate File 动作详解:动态构造 CSV、Text、PDF 文件并触发下载

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ToolJet Generate File 动作详解:动态构造 CSV、Text、PDF 文件并触发下载

ToolJet Generate File 动作详解:动态构造 CSV、Text、PDF 文件并触发下载

【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 🚀项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet

Generate file 是 ToolJet 内置的一种客户端动作(Action),用于在运行时根据动态数据即时构造文件并直接触发浏览器下载,典型场景包括"一键导出表格数据为 CSV"、"生成纯文本报告"、"以 PDF 表格形式输出查询结果"等。本文基于官方文档 generate-file.md 的完整配置说明展开,并结合 前端事件调度实现、文件生成核心库 与 CSV 序列化实现,讲清楚每种文件类型对 Data 字段的格式要求、默认值行为以及底层生成原理,读完后可直接在 App Builder 和 RunJS 中正确使用该动作。

动作定位与执行链路

从官方文档描述看,该动作"允许你在运行时构造文件并让用户下载"。在前端源码中,它对应事件类型generate-file,与runQueryshowAlertgoToApp等并列注册为可在 RunJS 中调用的动作之一(见 actions.js 中的动作清单)。

事件分发逻辑位于 eventsSlice.js:

case 'generate-file': { const data = getResolvedValue(event.data, customVariables, moduleId) || []; const fileName = getResolvedValue(event.fileName, customVariables, moduleId) || 'data.txt'; const fileType = getResolvedValue(event.fileType, customVariables, moduleId) || 'csv'; const fileData = { csv: generateCSV, plaintext: (plaintext) => plaintext, pdf: (pdfData) => pdfData, }fileType; return generateFile(fileName, fileData, fileType); }

这段代码揭示了三个源码级事实:

  1. 所有字段都经过变量解析datafileNamefileType均通过getResolvedValue解析,因此支持{{...}}动态变量引用;
  2. 存在隐式默认值:Data 为空时回退为[],File name 为空时回退为data.txt,Type 为空时回退为csv
  3. 文本类型的内部标识是plaintext而非text:虽然 UI 选项表中 Type 写作CSVTextPDF,但序列化映射表的键是csv/plaintext/pdf,这一点在 RunJS 中调用时尤为关键(见下文)。

配置项全解

官方文档给出了如下四个选项,本文逐一补充其在源码中的落地行为:

Option说明源码层面的行为
Type要生成的文件类型:CSVTextPDF内部取值为csv/plaintext/pdf,决定 Data 的序列化方式;未填时默认为csv
File name生成文件的名称未填时默认为data.txt,支持变量插值
Data用于构造文件的数据,格式随文件类型而定为空时默认为[],支持{{...}}动态表达式
Debounce默认空;填入数字表示该毫秒数后才执行动作,如300事件节流配置,避免高频事件(如连续输入)反复触发文件下载

其中 Debounce 字段对交互密集型场景很有价值:例如在输入事件上挂载 generate file 时,填入300可使动作在用户停止触发 300ms 后才真正执行一次,避免产生大量重复下载。

三种文件类型的数据格式要求

CSV:对象数组,键即列头

使用CSV格式时,Data 字段应是一个对象数组,ToolJet 假定每个对象的键都相同,并将这些键作为 CSV 的列头。官方文档示例:

{{ [ { name: 'John', email: 'john@tooljet.com' }, { name: 'Sarah', email: 'sarah@tooljet.com' }, ] }}

生成结果为:

name,email John,john@tooljet.com Sarah,sarah@tooljet.com

这一行为由 generate-csv.js 实现,仅 5 行核心逻辑:

import Papa from 'papaparse'; export default function generateCSV(records) { return Papa.unparse(records); }

即底层直接委托给 papaparse 的Papa.unparse完成"对象数组 → CSV 文本"的序列化。这意味着字段中包含逗号、引号、换行符等字符时会按 RFC 4180 标准自动加引号转义,可直接粘贴到 Excel 等工具中解析。

Text:字符串;对象数组需先序列化

使用Text格式时,Data 字段应直接是一个字符串。如果数据源是对象数组(例如表格组件的当前页数据),必须先stringify再传入 Data 字段。官方文档给出的示例是:

{{JSON.stringify(components.table1.currentPageData)}}

对应源码中plaintext的序列化函数是恒等函数(plaintext) => plaintext,即不做任何转换、原样写入文件——这也解释了为什么必须自行完成序列化:若直接传对象数组,Blob会得到无意义的[object Object]内容。

PDF:字符串或对象数组,二选一

PDF 支持两种输入形态,行为差异在 generate-file.js 的generatePDF函数中清晰可见:

  • 传入字符串:生成纯文本 PDF。源码中以doc.text(value, x, y, { align: 'left', maxWidth: pageWidth - 2 * margin })逐行绘制,页边距margin = 10
  • 传入对象数组:生成表格形态的 PDF。源码以数组第一个元素的键作为表头,调用 jspdf-autotable 的doc.autoTable({ head: [columnNames], body: value.map((item) => Object.values(item)) })渲染出带行列的表格,并依据doc.lastAutoTable.finalY控制后续内容的起始位置;
  • 传入单个对象:同样渲染为表格,只是 body 只有一行数据;
  • 其他类型(数字、布尔等):抛出Invalid data type. Expected string, object, or array.错误。

底层生成机制:Blob 下载与 PDF 动态加载

generate-file.js 的generateFile主函数处理 CSV 与文本文件的下载:

const type = fileType === 'csv' ? 'text/csv' : 'text/plain'; const blob = new Blob([data], { type }); if (window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveBlob(blob, filename); } else { const elem = window.document.createElement('a'); elem.href = window.URL.createObjectURL(blob); elem.download = filename; document.body.appendChild(elem); elem.click(); document.body.removeChild(elem); window.URL.revokeObjectURL(elem.href); }

要点:

  • CSV 使用text/csvMIME 类型,其余(plaintext)使用text/plain
  • 兼容旧版 IE/Edge 的msSaveOrOpenBlob接口,现代浏览器走标准的"创建<a>元素 +URL.createObjectURL+ 模拟点击"流程,并在使用后revokeObjectURL释放内存,避免 Blob URL 泄漏;
  • 全程在浏览器端完成,数据不经过服务端中转,适合包含敏感数据的本地导出场景。

PDF 则采用动态 import按需加载(await import('jspdf'),见 generate-file.js L22-L26),jspdf 体积较大,按需引入可避免首屏加载负担;同时对 ESM/CJS 两种导出形式都做了兼容取值(jsPDFNamespace.jsPDF || jsPDFNamespace.default)。

通过 RunJS 调用 generate file

除在组件事件(Events)中配置外,该动作同样可在 RunJS 代码中调用,官方文档在 run-action-from-runjs.md 中给出了签名与示例:

actions.generateFile('<fileName>', '<fileType>', '<data>')

三个实战示例(均出自该文档):

// 以表格当前页数据生成 CSV 文件 csvfile1 actions.generateFile('csvfile1', 'csv', '{{components.table1.currentPageData}}') // 以字符串化后的表格数据生成文本文件 textfile1 actions.generateFile('textfile1', 'plaintext', '{{JSON.stringify(components.table1.currentPageData)}}') // 以表格当前页数据生成 PDF 表格文件 Pdffile1 actions.generateFile('Pdffile1', 'pdf', '{{components.table1.currentPageData}}')

RunJS 桥接实现位于 eventsSlice.js L1298-L1310:内部先校验三个参数均非空(缺失时弹出Action failed: fileName, fileType and data are required错误提示),再构造actionId: 'generate-file'的事件对象并复用与 UI 完全相同的executeAction执行通道——这意味着 RunJS 调用与事件面板配置走的是同一条执行链路,行为完全一致。

使用要点小结

  1. 参数命名与文档一致fileNamefileTypedata三个字段都支持{{...}}变量表达式,可引用查询结果、组件数据或全局变量;
  2. 文本类型务必传字符串:UI 中 Type 选择Text后,内部类型值是plaintext;若数据是对象数组,请在 Data 字段中显式JSON.stringify
  3. CSV 列头来自对象的键:确保数组中各对象键集一致,列头顺序即对象键的顺序;
  4. PDF 想要表格效果就传对象数组,想要纯文本就传字符串;
  5. 善用 Debounce:在高频触发的事件上配置毫秒级延迟,避免重复下载。

以上配置与行为均可在当前仓库中直接查证:文档主体见 generate-file.md,事件分发见 eventsSlice.js,文件生成核心见 generate-file.js 与 generate-csv.js,RunJS 调用说明见 run-action-from-runjs.md。

【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 🚀项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/6 18:47:45

北航数值分析历年试题复习指南:从插值到ODE的高频考点与刷题策略

简介&#xff1a;北京航空航天大学数值分析历年试题整理以单文件PDF形式呈现&#xff0c;压缩包整体约8.74MB&#xff0c;适合正在学习或备考该课程的高年级本科生与研究生使用。这份材料系统收录了多年考试真题及参考解答&#xff0c;覆盖误差分析、线性代数数值方法、非线性方…

作者头像 李华
网站建设 2026/9/6 18:45:15

基于Python的指数与Weibull分布可靠性建模与维护决策优化

简介&#xff1a;一套基于Python的系统组件可靠性评估与优化复现资源&#xff0c;完整覆盖论文中的关键分析流程。面向具备概率统计和编程基础的可靠性工程师、系统设计研发人员&#xff0c;重点解决单个组件2年无故障生存概率、平均故障时间&#xff08;MTTF&#xff09;计算、…

作者头像 李华
网站建设 2026/9/6 18:44:41

ICEM CFD简明教程:从几何清理到六面体网格划分实战指南

简介&#xff1a;这是面向ANSYS ICEM CFD初中级用户的一本简明中文教程&#xff0c;重点解决结构网格划分中最关键的“拓扑思路”与分块策略积累问题&#xff0c;而非单纯讲解界面操作。内容从ICEM CFD概述、文件类型、几何创建与导入&#xff0c;到网格生成、质量检查与编辑均…

作者头像 李华
网站建设 2026/9/6 18:41:25

斜盘式轴向柱塞泵毕业设计全解析:从参数计算到答辩要点

简介&#xff1a;这是一份面向机械设计及车辆工程专业学生的柱塞泵毕业设计完整资料&#xff0c;源自淮海工学院机械工程学院的实际课题任务&#xff0c;聚焦高压小流量输送场景下柱塞泵的结构分析、参数确定与制图表达。文档内含毕业设计任务书、开题报告、外文翻译、实习报告…

作者头像 李华