news 2026/9/10 18:37:16

ToolJet 实战:基于 AWS S3 构建文件上传与下载界面(完整 Queries 与 Widgets 配置指南)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ToolJet 实战:基于 AWS S3 构建文件上传与下载界面(完整 Queries 与 Widgets 配置指南)

ToolJet 实战:基于 AWS S3 构建文件上传与下载界面(完整 Queries 与 Widgets 配置指南)

【免费下载链接】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

本文是一份基于 ToolJet 官方 how-to 指南整理与源码扩充的实战教程,讲解如何在不写任何后端代码的前提下,使用 ToolJet 的 App Builder 组合 Dropdown、Table、Text Input、File Picker 与 Button 等组件,配合 AWS S3 数据源的 4 条核心查询(getBuckets、listObjects、uploadToS3、download),快速搭建一个可浏览 Bucket、列出对象、上传文件并生成下载链接的 S3 文件管理界面。读完本文,你将掌握 ToolJet 查询与组件之间的数据绑定、事件驱动刷新以及 base64 文件上传的标准写法,并了解底层 S3 查询服务的实现原理。

前置条件:先接入 AWS S3 数据源

在开始搭建 UI 之前,必须先完成 AWS S3 数据源(Data Source)的接入。ToolJet 官方文档在 AWS S3 数据源指南 中详细说明了配置方式,这里提炼关键步骤作为实战前置:

  1. 点击查询面板(Query Panel)左下角的+ 添加新数据源(Add new Data source)按钮,或从 ToolJet 仪表盘的数据源(Data Sources)页面进入;
  2. 选择Amazon AWS S3数据源;
  3. 根据你的运行环境选择认证方式,ToolJet 支持以下三种:
认证方式需要提供的参数适用场景
IAM Access KeysRegion、Access key、Secret key最常见的长期凭证方式,官方建议为此创建专用 IAM 用户,便于控制 ToolJet 的访问权限级别
AWS Instance CredentialsRegion(勾选 Use AWS Instance Credentials)ToolJet 运行在 EC2/ECS 上时,直接复用实例绑定的 IAM 角色
AWS ARN RoleRegion、Role ARN需要跨账号或按角色授权时,通过 STS AssumeRole 换取临时凭证

:::tip 如果使用的是非 AWS 的 S3 兼容存储,还可以通过自定义 endpoint 连接不同的 S3 Host,详见 S3 Custom Endpoints 指南(本文主题不展开)。 :::

从源码角度看,上述三种认证方式在 S3 插件中有对应的实现分支。以 插件实现 中的getConnection方法为例:

  • 选择AWS Instance Credentials时,使用 AWS SDK 的fromInstanceMetadata()创建S3Client,其内部通过timeout: 5000maxRetries: 1控制元数据服务的访问超时与重试;
  • 选择AWS ARN Role时,插件会调用 getAssumeRoleCredentials,通过 STS 的AssumeRoleCommand换取临时凭证(AccessKeyId、SecretAccessKey、SessionToken)后再创建客户端;
  • 使用IAM Access Keys时,直接以access_key/secret_key构造凭证。

构建 UI:五个 Widgets 各司其职

接入数据源后,在 App Builder 画布上拖入以下组件,构成整个 S3 文件管理界面的骨架:

Widget作用
Dropdown用于选择 S3 存储桶(Bucket),其选项来自getBuckets查询结果
Table用于列出所选 Bucket 内的全部对象(文件),数据来自listObjects查询结果
Text Input用于输入文件上传的目标路径(前缀目录)
File Picker用于选择要上传的本地文件
Button用于触发上传查询(uploadToS3

这 5 个组件分别承担"选桶 → 看文件 → 定路径 → 选文件 → 触发上传"的完整交互链路。下图是搭建完成后的界面效果:

四条核心 Queries 的完整配置

本次实战共需要创建 4 条查询,分别完成"列桶、列对象、生成下载链接、上传文件"四项能力。接下来逐一讲解每条查询的创建方式与参数绑定。

getBuckets:拉取全部存储桶

操作(Operation):选择List buckets(列出所有桶),该操作不需要任何参数。

步骤:新建查询 → 选择 AWS S3 数据源 → 操作选择List buckets→ 将查询命名为getBuckets→ 点击Save保存。

从源码看,ListBuckets操作最终由 listBuckets 函数 执行:构造一个空的ListBucketsCommand({})并发送给 S3 客户端,返回的响应结构为{ Buckets: [...], Owner: {...} },其中Buckets是对象数组,每个元素含Name(桶名)、CreationDate(创建时间)等字段。这正是下一步 Dropdown 数据绑定的依据。

配置 Dropdown 绑定桶列表

选中画布上的Dropdown组件,进入其属性面板,做如下配置:

  • Label(标签):设置为Bucket,作为界面上的提示文案;
  • Option values(选项值):设置为
    {{queries.getBuckets.data.Buckets.map(bucket => bucket['Name'])}}

    将查询返回的Buckets对象数组映射为桶名字符串数组;

  • Option label(选项标签):同样设置为
    {{queries.getBuckets.data.Buckets.map(bucket => bucket['Name'])}}

    让界面显示的标签与底层值保持一致(显示桶名、值也是桶名)。

:::info{{ }}是 ToolJet 的表达式语法(类似模板字符串),可以在任意属性中输入 JavaScript 表达式,并直接引用queries.<查询名>.datacomponents.<组件名>等全局对象。这里的map操作是因为Buckets是对象数组,而 Dropdown 的选项值需要的是字符串数组。 :::

事件衔接:可以给 Dropdown 添加事件处理器(Event Handler),当用户从下拉框选中某个桶时,自动触发运行listObjects查询,从而联动刷新表格数据。这个联动是后续所有动态行为的基础。

listObjects:列出选中桶内的全部对象

操作(Operation):选择List objects in a bucket(列出桶中的对象)。

参数配置:在Bucket字段中输入

{{components.dropdown1.value}}

这样查询执行时,会动态取 Dropdown 当前选中的桶名,而不是写死某个桶。

从源码可以更深入地理解这个操作的行为。在 listObjects 函数 中,插件将查询参数映射为 AWS SDK v3 的ListObjectsV2CommandInput

ToolJet 查询参数SDK 字段说明
BucketBucket桶名(必填)
PrefixPrefix可选,按前缀过滤,例如只列出images/下的对象
Max keysMaxKeys可选,单次最多返回的对象数量
OffsetStartAfter可选,从某个键名之后开始列举(等效于按前缀起始位置列举)
Next Continuation TokenContinuationToken可选,当结果被截断时,用响应中的令牌取下一页

列表操作返回的响应中,Contents字段是对象数组,每个元素包含Key(对象键,即文件路径)、LastModified(最后修改时间)、Size(大小,字节)、ETagStorageClass等元数据,这些字段将直接用于 Table 组件的列绑定。

配置 Table 展示对象列表

选中Table组件,按以下方式配置其属性:

  • Table data(表数据)
    {{queries.listObjects.data['Contents']}}

    将表格数据源绑定到listObjects查询返回的对象数组。注意这里用data['Contents']而不是data.Contents,两种写法等价,但后者在某些包含特殊字符的字段名场景下更稳妥;

  • 添加列(Add Columns)
Column Name(列名)Key(数据键)
第 1 列KeyKey
第 2 列Last ModifiedLastModified
第 3 列SizeSize
  • 添加操作按钮(Action button):添加一个按钮,按钮文本设为Copy signed URL,并为其添加事件处理器:事件选择On Click,动作(Action)选择Copy to clipboard,在文本字段中输入
    {{queries.download.data.url}}

    这样点击按钮时,会把download查询生成的签名下载 URL 复制到剪贴板。

download:为选中对象生成签名下载 URL

操作(Operation):选择Signed URL for download(生成下载签名 URL)。

参数配置

  • Bucket
    {{components.dropdown1.value}}
  • Key
    {{components.table1.selectedRow.Key}}

    使用 Table 组件当前选中行的Key字段,实现"点哪行、签哪行"的动态绑定。

事件衔接:回到 Table 组件的属性面板,添加一个事件处理器:Event选择Row clicked(行点击),Action选择Run queryQuery选择download。这样每当用户点击表格中的任意一行,都会触发download查询,为该行对象生成新的签名下载 URL。

:::info 签名 URL(Signed URL / Presigned URL)是对象所有者用自己的安全凭证为他人生成的、带时间限制的下载链接。其关键特性是"临时有效",过期后链接失效,从而在不暴露 AWS 凭证的前提下安全共享对象。 :::

从源码看,该操作由 signedUrlForGet 函数 实现:插件构造GetObjectCommand后,调用 AWS SDK 的getSignedUrl()方法生成 URL,其中expiresIn参数控制有效期,默认值为 3600 秒(1 小时),查询面板中可通过Expires in参数覆盖默认值。返回结构为{ url: "https://..." },这就是上文中"Copy signed URL"按钮绑定queries.download.data.url的来源。

uploadToS3:将本地文件上传到指定路径

操作(Operation):选择Upload object(上传对象)。

参数配置(这是本教程中信息密度最高、也最容易踩坑的一组绑定):

参数字段表达式含义
Bucket{{components.dropdown1.value}}目标桶名,动态取 Dropdown 当前选中值
Key{{ components.textinput1.value + '/' + components.filepicker1.file[0].name }}上传路径:Text Input 输入的目录 +/+ 文件名
Content type{{components.filepicker1.file[0].type}}文件的 MIME 类型,由 File Picker 自动读取
Upload data{{components.filepicker1.file[0].base64Data}}文件的 base64 编码内容
Encodingbase64告知数据源上传数据是 base64 编码,需要解码后写入

这里的几个绑定点值得展开说明其底层逻辑:

  1. components.filepicker1.file是文件对象数组。ToolJet 的 File Picker 组件在useFilePicker钩子中(frontend/src/AppBuilder/Widgets/FilePicker/hooks/useFilePicker.js)通过FileReaderreadAsDataURL读取文件,将结果拆出 base64 部分存入base64Data字段,同时保留name(文件名)、type(MIME 类型)、sizeBytes(大小)等元数据。因此file[0]表示第一个文件,file[0].namefile[0].typefile[0].base64Data分别对应文件名、类型与内容。这也是为什么Max file count要设为 1——保证file[0]就是唯一且确定的文件。
  2. Encodingbase64时,服务端会做解码。在 uploadObject 函数 中,插件用Buffer.from(data, encoding)Upload data按指定编码转换成二进制Buffer,再作为PutObjectCommandBody发送;ContentEncoding也会被一并设置。若你的文件内容不是 base64 编码,则保持默认的utf8即可。
  3. Content type 会被写入对象的元数据ContentType参数会传给 S3 的PutObjectCommand,决定对象下载时的响应 Content-Type 头,因此建议从 File Picker 动态读取文件真实类型,而不是写死。

配置 File Picker:限定文件类型与数量

点击 File Picker 组件的属性手柄(widget handle),进入属性面板进行以下配置:

  • Accept file types(接受的文件类型)
    • 只接受 PDF:{{"application/pdf"}}
    • 只接受图片:{{"image/*"}}
    • 接受任意类型:留空
  • Max file count(最大文件数){{1}},因为每次只上传 1 个文件。

:::infoAccept file types必须是符合 input 元素规范的合法 MIME 类型(如application/pdfimage/*)或合法的文件扩展名。要接受任意类型文件,将该属性设为空值即可。 :::

从组件定义看,该属性在 File Picker 组件定义 中对应validation.fileType字段,默认值为'image/*';而maxFileCount的默认值为2(见 filepicker.js),并且仅在启用多文件模式(enableMultiple)时才渲染显示。useFilePicker钩子中同样以maxFileCount作为上限校验依据(useFilePicker.js),超出数量会提示 "You can select a maximum of N files."。因此本次实战将两个值分别设为application/pdf{{1}},既限定了类型,也限定了数量。

收尾:上传成功后自动刷新对象列表

最后一步是让整个流程"闭环"。进入uploadToS3查询的Advanced(高级)选项卡,添加一个成功事件处理器(On Success):

  • EventQuery Success
  • ActionRun query
  • QuerylistObjects

这样,每当文件上传成功,listObjects查询会自动重新执行,Table 中的数据随即刷新,新上传的文件立刻出现在列表中,无需手动点击任何刷新按钮。

至此,整个 S3 文件管理应用的核心链路就完整了:

  1. 页面加载时运行getBuckets,Dropdown 填充全部桶名;
  2. 用户选择桶,触发listObjects,Table 列出桶内所有对象;
  3. 用户点击某一行,触发download,生成该对象的签名下载 URL,可通过"Copy signed URL"按钮复制;
  4. 用户在 Text Input 输入目标目录、用 File Picker 选择文件,点击 Button 触发uploadToS3上传;
  5. 上传成功后自动重跑listObjects,表格即时刷新。

延伸:还能做哪些扩展

基于同样的"查询 + 组件 + 事件"模式,结合 S3 数据源支持的操作清单(其底层实现均可参考 operations.ts),你可以很方便地扩展更多能力:

  • Read object(读取对象):直接读取对象内容并返回字符串,适合预览文本类文件;
  • Remove object(删除对象):可在 Table 中再添加一个"删除"操作按钮,绑定{{components.table1.selectedRow.Key}}后触发删除查询;
  • Signed URL for upload(上传签名 URL):如果希望让不具备 AWS 凭证的外部用户直接向桶内上传,可以生成上传签名 URL 交给客户端直传;
  • Create a new bucket(新建桶):结合 Text Input 输入桶名,即可在界面内完成建桶操作。

此外,S3 插件还支持allow_dynamic_connection_parameters开关(默认开启),它决定查询中的 Bucket 参数是采用查询级动态值还是回退到数据源配置的默认桶名(见 插件入口),在多环境、多桶切换场景下非常实用。

如果需要更完整的可运行示例,仓库中还提供了官方 S3 浏览应用的教程链接与配套截图,可结合本文逐步复现。整个方案的实现思路同样适用于 ToolJet 支持的其他对象存储数据源(如 GCS、MinIO 等),一通百通。

【免费下载链接】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/10 18:36:56

基于西门子S7-1200的锅炉自动化控制系统开发实践

1. 锅炉自动化控制系统开发概述锅炉作为工业生产中的核心热力设备&#xff0c;其控制系统的自动化程度直接影响着能源利用率、安全性和运行稳定性。传统的手动控制方式已无法满足现代工业对精确温控、节能环保和安全运行的要求。西门子S7-1200系列PLC凭借其模块化设计、强大的通…

作者头像 李华
网站建设 2026/9/10 18:35:39

Python实现服务器存储设备自动化检测脚本开发指南

1. 项目背景与需求分析在服务器测试工作中&#xff0c;存储设备的检测是基础但极其重要的一环。传统的人工逐块检查硬盘的方式效率低下&#xff0c;特别是在面对12块甚至更多硬盘的服务器配置时&#xff0c;测试工程师往往需要花费大量时间重复执行相同的检查步骤。这不仅消耗人…

作者头像 李华
网站建设 2026/9/10 18:35:10

GEE格网系统解析与空间分析实践

1. 理解GEE中的格网系统Google Earth Engine&#xff08;GEE&#xff09;作为一款强大的地理空间分析平台&#xff0c;其核心功能之一就是对大规模栅格数据进行高效处理。而这一切的基础&#xff0c;正是格网&#xff08;Grid&#xff09;系统。格网在GEE中扮演着数据组织的骨架…

作者头像 李华
网站建设 2026/9/10 18:33:35

用Codex+Relay实现移动端全栈开发:从原型到交付的完整实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 18:32:48

GEO培训机构怎么选?2026年实战派鉴别指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华