☰
n8n 二进制数据处理入门:彻底掌握 $binary 槽位、Code 节点字节读写与文件大小陷阱
2026/10/9 2:42:49 网站建设 项目流程
  • AI 技能
  • AI 插件
  • 工作流自动化
  • 流程编排

【免费下载链接】n8n-skills

n8n skillset for Claude Code to build flawless n8n workflows

项目地址:https://gitcode.com/gh_mirrors/n8/n8n-skills
点击查看免费下载

n8n 中的每一个工作流条目(item)都同时携带两个互不干扰的顶层槽位:$json存放结构化数据,$binary存放真实文件字节。几乎所有文件类 Bug——下载的 PDF 变成乱码、邮件附件丢失、AI 工具拿不到上传图片——根源都是没搞清这两个槽位的边界。本文以skills/n8n-binary-and-data/BINARY_BASICS.md为骨架,结合仓库内SKILL.md、MERGE_FOR_CONTEXT.md及 n8n-mcp 工具约定,系统讲解$binary槽位的完整形状、产生与消费它的节点、Code 节点中的读写姿势、Mime 类型约定、文件大小上限,以及如何在执行记录中确认文件真的“活”过了每一个节点。


一、槽位形状:$json与$binary是两个独立命名空间

每个 item 的顶层只有两个键。json是你的业务数据,binary是你的文件。它们完全独立——一个只改写json的转换节点不会自动帮你携带binary,反之亦然。这是 n8n 二进制机制的第一性原理,也是 90% 二进制 Bug 的共同根源(这一点在 SKILL.md 中被总结为第一条规则)。

{ "json": { "customerId": 42, "status": "sent" }, "binary": { "invoice": { "data": "<base64-encoded bytes>", "mimeType": "application/pdf", "fileName": "invoice-42.pdf", "fileExtension": "pdf", "fileSize": "12 kB" } } }

二进制属性名(binary property name)

binary内部的键——上例中的invoice——叫做二进制属性名。它可以是任意字符串,但data是大多数节点的默认值:当没有任何信息提示你该用哪个键时,默认按$binary.data处理。

文件类节点会暴露一个binaryPropertyName参数来指向这个键。整个协作模式是:生产者命名槽位,消费者按这个精确名字引用。消费者写错名字,它找的就是一个根本不存在的槽位——不报错,只是拿不到文件。

四个关键字段

字段含义
data字节内容,base64 编码
mimeType告诉消费者如何解释这些字节(application/pdf、image/png……)
fileName供邮件附件、上传、下载到磁盘使用
fileExtension通常从fileName推导而来;部分节点直接使用它

表达式层面同样遵循这个分离:{{ $binary.invoice.fileName }}读取的是文件元数据,{{ $json.customerId }}读取的是数据,二者从不混用(见 SKILL.md)。


二、哪些节点产生 binary

你几乎不需要手搓槽位——由节点来填充:

节点要设置什么结果
HTTP RequestresponseFormat: "file"响应体进入$binary.data(或options中指定的名字)
Read/Write Files from Disk(读取)文件路径文件内容进入$binary
S3 / Google Drive / Dropbox(下载)文件引用下载的文件进入$binary.<key>
邮件触发器(IMAP、Gmail 触发器)开启附件处理每个附件进入$binary
云厂商 AI 媒体节点(图片/音频生成)options.binaryPropertyOutput生成字节进入指定槽位

头号 Bug:HTTP 下载忘了改responseFormat

最常见的问题是把 HTTP Request 下载留在默认的响应格式上。没有responseFormat: "file",n8n 会尝试把响应体当作 JSON 或文本解析,你得到的是$json里一团损坏的字符串,而不是$binary里干净的字节。

在 n8n-mcp 工作流里,正确姿势是用get_node核对nodes-base.httpRequest的字段定义——响应处理相关的选项在不同 n8n 版本下形态不同,绝不要凭记忆写参数名。这正是 get-node.sh 前置钩子反复强调“先确认参数名再配置节点”的原因。

第二陷阱:云厂商 AI 媒体节点默认不吐字节

图片生成、文本转语音这类 Provider AI 节点是另一个反复出现的坑:很多节点除非你显式设置options.binaryPropertyOutput,否则根本不产出 binary。没设置的话,下一个节点的上传操作将无米下锅。无论写入还是读取,都先跑一次get_node确认字段在当前版本上的确切名称。


三、哪些节点消费 binary

消费者同样通过属性名引用槽位:

节点如何引用 binary
Email(发送)附件字段指向binaryPropertyName
Slack(发送文件)引用二进制属性
HTTP Request(multipart/form-data)在 body 参数中引用 binary
存储上传(S3、R2、Drive)把 binary 作为请求体引用
Write Files to Disk把命名二进制属性写入某个路径

模式始终一致:生产者命名属性,消费者指向那个名字。绝大多数“文件没附上”的 Bug 都是两端属性名不匹配——用get_node核对两端的参数定义,并在执行记录里确认(见下文“在执行中检查 binary”一节)。


四、在 Code 节点中读取二进制

大多数工作流根本不需要“看”字节——直接把 binary 透传给下游消费者即可。当你确实需要字节时(哈希、解析、文本提取),在 Code 节点中使用getBinaryDataBuffer。

⚠️ 不要自己抓$binary.<key>.data再手动 base64 解码。该助手会替你处理 n8n 的存储模式差异(内存模式 vs 文件系统模式),手动解码在两种模式下行为不一致。

// Code 节点,"Run Once for Each Item"(每个条目执行一次) const buffer = await this.helpers.getBinaryDataBuffer(0, 'data'); // (itemIndex, propertyName) const text = buffer.toString('utf-8'); // 适用于文本类文件 const length = buffer.length; return [{ json: { ...$json, length }, binary: $input.item.binary, // ← 一定要把文件传下去,否则经过这个节点文件就没了 }];

getBinaryDataBuffer(itemIndex, propertyName)返回一个 NodeBuffer。你可以像对待任何 Buffer 一样切片、哈希、解码。语言层面的细节(存在哪些助手、执行模式、$input与$json的区别)属于 n8n-code-javascript 技能;二进制特有的规则只有注释里那一条:如果你在 return 里不带binary,文件就在这个节点被丢弃。

关于 Code 节点两个槽位的边界,SKILL.md 还强调了一个常见误区:Code 节点返回[{ json: {...} }]而不重新挂载binary,就是静默丢文件的典型写法;这也是仓库 README.md 里列出的六大可防问题之一。

为什么toString('utf-8')读不了 PDF

读取 PDF 的文本并不是buffer.toString('utf-8')那么简单——PDF 是二进制容器,不是 UTF-8 文本。你需要真正的解析步骤(OCR/提取节点,或在一个具备相应库的环境里用专门库)。Buffer 给你的是字节;把它们变成可读文本是另一个独立问题。

这一条提醒同样适用于 ZIP、XLSX 等复合格式:Buffer解决的是“拿到字节”,文件格式解析是下一步的独立任务。


五、在 Code 节点中写入二进制

自己构建槽位:先把字节做 base64,再补上 mime 类型和文件名,让下游消费者知道它们拿到的是什么。

const text = 'Hello, world!'; return [{ json: { ok: true }, binary: { report: { data: Buffer.from(text).toString('base64'), mimeType: 'text/plain', fileName: 'report.txt', fileExtension: 'txt', }, }, }];

永远设置mimeType。省略它,下游消费者可能拒收文件或渲染错误——邮件无法干净地附加附件,Slack 只显示通用文件图标而不是内联图片。写入时补全这四个字段,就是给下游的完整契约。


六、Mime 类型:生产者与消费者之间的契约

mimeType是生产者和消费者之间的契约。错误的值不会报错——它会让消费者行为异常:拒绝附加、把本该内联的图片变成下载、显示破碎的缩略图。

文件类型Mime 类型
PDFapplication/pdf
PNGimage/png
JPEGimage/jpeg
纯文本text/plain
JSONapplication/json
CSVtext/csv
XLSXapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet
ZIPapplication/zip

魔数嗅探(magic-byte sniffing)

当上游不告诉你类型时,从文件开头的字节判断:PDF 以%PDF-开头,PNG 以\x89PNG开头,JPEG 以\xFF\xD8\xFF开头。在 Code 节点里写几行魔数检查,是当上游元数据不可信时最可靠的兜底方案——读到的 Buffer 本身就足够做这种前几个字节的比对。


七、文件大小限制:何时该卸载到外部存储

执行数据会存进 n8n 的数据库,大块 base64 会撑爆数据库并拖慢实例。粗略的规模判断:

单槽位大小结论
几 MB没问题
几十 MB能用,但更慢;盯紧实例内存
100 MB+卸载到外部存储,只传 URL/ID

大文件的推荐模式

对大文件的正确姿势是:字节一产生就上传到对象存储,把 URL 或 key 作为普通 JSON 在整个工作流里传递,只在真正需要字节的那个节点重新拉取。这样每个条目的载荷保持很小,执行保持快。

如果自托管实例使用的是文件系统二进制数据模式(而非内存模式),数据库压力会低一些,但真正的大文件依然适用同样的卸载建议——二进制数据模式只影响存储介质,不影响“别在 JSON 里搬运大字节”的原则。

这一策略与仓库中 AGENT_TOOL_BINARY.md 的“预置存储、JSON 传 key/URL”模式一脉相承——在 AI Agent 工具边界上,同样的上传早、传引用原则是唯一可行通道。


八、在执行中检查 binary:验证救不了你的静默失败

validate_workflow不会告诉你 binary 是否存活过一个节点——槽位被丢弃是静默失败,验证通过不代表文件还在。唯一可靠的检查是执行本身(这一点在 SKILL.md 的“Verifying binary survived”一节同样被强调)。

检查三步走:

  1. 运行工作流(用n8n_test_workflow,或真实触发)。
  2. 用n8n_executions拉取执行记录,查看每个节点的输出中binary槽位。
  3. 槽位即使 base64 大到无法完整渲染,也会显示存在性和元数据(名称、mime 类型、大小)。你要检查的就是它在每个节点上的出现/消失。

binary最后一次出现、随后在下一个节点消失的那个节点,正是需要加透传(pass-through)或 Merge 的位置。修复方案参见 MERGE_FOR_CONTEXT.md:让 binary 走一条不被触碰的分支,再用combineByPosition模式按位置重组 JSON 与 binary。用 n8n-mcp 实现时,节点参数名(mode、combineBy、combineByPosition、输入个数)在不同 Merge 版本间移动过,提交结构前先用get_node确认nodes-base.merge的当前形态——原理稳定,字段名会变。

开发期间建议每过一个节点就检查一次执行记录,而不是在整条链跑完后才看——因为原始 binary 一旦被丢弃就再也找不回来了(MERGE_FOR_CONTEXT.md 的常见错误表把“发现得太晚”列在第一位)。


九、当 binary 是触发输入时

对于接收文件的工作流——multipart webhook 上传、邮件附件、被监听的文件夹——binary 出现在触发器的输出上:

  • 从触发器开始,就用它的二进制属性名引用它。
  • 让每个需要它的下游节点都把它透传下去(每个节点都可能是潜在剥离点)。

如果 binary 没出现在触发器输出,检查两处:

  • Content-type 处理。接收multipart/form-data的 Webhook 会把文件放进$binary、把表单字段放进$json.body;接收 JSON 的 Webhook 则完全没有 binary。$json.body的表达式级细节属于 n8n-expression-syntax 技能(SKILL.md 也特别强调了这个“上传的文件根本不在$json下面”的误区)。
  • 触发器自身的二进制设置。部分触发器除非显式告诉它下载附件,否则会跳过附件。

十、速查清单:构建二进制安全工作流的自检项

围绕本文内容,结合 SKILL.md 的官方清单,收尾前逐项确认:

  • 文件内容从$binary.<key>读取——绝不从$json读
  • HTTP 下载使用responseFormat: "file"
  • Code 节点在需要文件继续流转时于 return 中重新挂载binary: $input.item.binary
  • JSON 转换节点要么透传 binary,要么用 Merge(combineByPosition)接回
  • 每个binary槽位都设置了mimeType(必要时用魔数嗅探兜底)
  • 大文件(100 MB+)上传到对象存储,工作流里只传 URL/ID
  • 用n8n_executions检查执行记录确认 binary 存活,而不是依赖验证结果
  • 触发输入场景下,确认 content-type 与触发器二进制设置没有吞掉附件

延伸阅读

本主题只是 n8n-binary-and-data 技能集的入口。仓库内的相邻资料按需取用:

文件何时阅读
SKILL.md三规则总纲、透传/Merge 保活、Agent 工具边界、CDN 需求
BINARY_BASICS.md本文原始出处——槽位解剖、Mime 类型、大小限制
MERGE_FOR_CONTEXT.mdJSON 转换后 binary 消失,用 Merge 按位置重接
AGENT_TOOL_BINARY.mdAI Agent 工具需要文件输入/产出文件时的边界处理
CDN_REQUIREMENT.md聊天界面展示图片需要 URL 而非原始字节
README.md技能能力总览与快速参考示例

记住核心心法:两个槽位并排同行——数据坐$json,文件坐$binary;一旦文件要跨过 AI Agent 工具或抵达聊天界面,它必须以 URL 而非字节的形式旅行。

  • AI 技能
  • AI 插件
  • 工作流自动化
  • 流程编排

【免费下载链接】n8n-skills

n8n skillset for Claude Code to build flawless n8n workflows

项目地址:https://gitcode.com/gh_mirrors/n8/n8n-skills
点击查看免费下载

相关推荐

上一篇:如何为winget-install开源项目贡献代码:从Fork仓库到提交PR的完整新手教程
下一篇:animal-island-ui Form表单系统详解:useForm、校验规则与布局完整教程

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询