news 2026/9/13 4:12:30

n8n-mcp 实战指南:深入理解 n8n `$binary` 插槽——从槽位结构到文件大小限制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
n8n-mcp 实战指南:深入理解 n8n `$binary` 插槽——从槽位结构到文件大小限制

n8n-mcp 实战指南:深入理解 n8n$binary插槽——从槽位结构到文件大小限制

【免费下载链接】n8n-mcpA MCP for Claude Desktop / Claude Code / Windsurf / Cursor to build n8n workflows for you项目地址: https://gitcode.com/GitHub_Trending/n8/n8n-mcp

导读

在 n8n 中,"文件"(PDF、图片、压缩包)从不直接存放在$json里,而是由每个 item 上的$binary插槽承载——数据走$json,文件走$binary,二者并行且互不干扰。本文以 n8n-mcp 仓库的 BINARY_BASICS.md 为核心,系统讲解$binary插槽的完整形态、哪些节点产出/消费二进制、在 Code 节点中如何读写字节、mime 类型契约、文件大小上限与执行过程排查方法。读完你将掌握"文件在 n8n 里到底存在哪、如何确保它活着到达消费节点"的完整技术链路。


一、插槽形态:$json$binary是互不相通的"双轨"

n8n 中每一个 item 都有两个顶层键json存放结构化数据,binary存放文件字节。两者相互独立——一个只改写json的转换节点不会自动携带binary,反之亦然。这是 n8n 二进制处理的第一性原理,也是 90% 二进制 bug 的根源(该原则在 SKILL.md 中被总结为三条铁律之一:文件内容在$binary,不在$json)。

一个典型 item 的完整形状如下(来自原文档):

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

1.1 二进制属性名(binary property name)

binary内部的键——这里的invoice——就是二进制属性名(binary property name)。它可以是任意字符串;data是大多数节点的默认名。文件处理类节点会暴露一个binaryPropertyName参数来指向这个键:生产者命名插槽,消费者按这个名字引用它。如果消费者端的名字写错,它就会去找一个不存在的插槽——文件"悄悄消失"的经典原因。

1.2 四个关键字段

字段含义
data字节内容,Base64 编码
mimeType消费者应如何解释这些字节(application/pdfimage/png……)
fileName用于邮件附件、上传、下载到磁盘等场景
fileExtension通常由fileName推导;部分节点直接使用它

表达式视角$json$binary是两个独立的命名空间,{{ $binary.invoice.fileName }}读文件元数据,{{ $json.customerId }}读数据,二者永不混用(详见 SKILL.md)。


二、哪些节点产出二进制(Producer)

几乎不需要手工拼装插槽——节点会帮你填充它:

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

2.1 最常见的下载 bug:HTTP Request 忘了responseFormat: "file"

如果 HTTP Request 保持默认的响应格式,n8n 会尝试把响应体当作 JSON 或文本解析——最终你得到的是$json里一段损坏的乱码字符串,而不是$binary里干净的字节。仓库中 enhanced-config-validator.ts 也印证了这一点:校验器会主动建议 API 端点显式设置options.response.response.responseFormat,并给出示例补丁:

{ "options": { "response": { "response": { "responseFormat": "json" } } } }

不同 n8n 版本的响应处理选项位于不同的结构之下,务必用get_node查询nodes-base.httpRequest确认当前版本的真实字段名(这条建议同样适用于下文所有"字段名随版本漂移"的参数)。

2.2 Provider AI 节点的隐藏开关

图像生成、文本转语音等 Provider AI 节点是另一个反复出现的坑:很多节点不显式设置options.binaryPropertyOutput就不会产出二进制。不设这个开关,下一个节点就没有任何东西可以上传。

补充说明:仓库的 example-generator.ts 在生成 FTP 上传示例时也使用了同族参数binaryData: true+binaryPropertyName: 'data'——"启用二进制 + 指定属性名"这一组合是 n8n 各节点上传文件的通用约定。


三、哪些节点消费二进制(Consumer)

消费者通过属性名引用插槽:

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

模式永远一致:生产者命名属性,消费者指向这个名字。绝大多数"文件没附上"的 bug 都是两端属性名不匹配——请同时用get_node核对两端字段,并检查执行记录验证。


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

大多数工作流根本不需要读字节——直接把二进制透传给消费者即可。当确实需要字节(哈希、解析、文本提取)时,在 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技能;二进制相关的唯一铁律就是上面注释里的那句:如果返回对象里不带binary,文件就会在这个节点被丢弃

仓库测试 node-specific-validators.test.ts 中也出现了this.helpers.getBinaryDataBuffer(0, "data")的用法,可作为该 API 在真实代码中签名(itemIndex, propertyName)的佐证。

PDF 文本提取警告buffer.toString('utf-8')对 PDF 无效——PDF 是二进制容器而非 UTF-8 文本。你需要在有解析库的环境里做真正的解析(OCR/提取节点或专用库)。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

当来源不告知类型时,可以从文件头字节嗅探:PDF 以%PDF-开头、PNG 以\x89PNG开头、JPEG 以\xFF\xD8\xFF开头。在 Code 节点里写几行"魔数"(magic bytes)检查,是无法信任上游元数据时的可靠兜底方案。


七、文件大小上限与外部存储卸载策略

执行数据存储在 n8n 的数据库中,巨大的 base64 块会撑大数据库并拖慢实例。粗略指导:

每个插槽的大小结论
几 MB没问题
几十 MB可用但更慢,留意实例内存
100 MB+卸载到外部存储,只传递 URL/ID

对大文件的推荐模式是:字节一产生就上传到对象存储,把 URL 或 key 作为纯 JSON 在工作流中传递,只在真正需要字节的那个节点重新拉取。这样每个 item 的负载都很小,执行也快。(如果自托管实例使用文件系统二进制数据模式而非内存模式,数据库压力会小一些,但对真正的大文件,同样的卸载建议依然成立。)

这与 SKILL.md 中"避免在 Code 节点硬编码 base64"的反模式一脉相承:硬编码会造成巨大的工作流 JSON、运行缓慢且易泄露。


八、在执行记录中检查二进制是否存活

validate_workflow不会告诉你二进制是否在某个节点幸存——插槽被丢弃是一种静默失败。唯一可靠的检查方法是看执行记录本身:

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

binary最后一次出现、紧接着在下一节点消失的位置,正是需要加透传或 Merge 的地方(具体模式见 MERGE_FOR_CONTEXT.md)。


九、当二进制是触发器输入时

对于接收文件的工作流——multipart webhook 上传、邮件附件、被监听的文件夹——二进制在触发器输出处到达:

  • 从触发器开始,就按它的二进制属性名引用。
  • 在每个需要它的下游节点透传(每个节点都可能成为"剥落点")。

如果二进制没有出现在触发器输出处,检查两点:

  • Content-type 处理:接收multipart/form-data的 Webhook 会把文件放进$binary、把表单字段放进$json.body;接收 JSON 的 Webhook 则完全没有二进制。$json.body的表达式细节属于n8n-expression-syntax
  • 触发器的二进制设置:有些触发器除非显式告知,否则会跳过附件下载。

十、把二进制带过 JSON 转换:Merge 兜底与透传

二进制最容易丢失的地方是JSON-only 节点(Edit Fields、Code、IF)——它们可能从输出中丢弃$binary插槽,而工作流校验照常通过、运行无报错,只是下游邮件节点要附件时文件已经不在了。两种保留方式(详见 MERGE_FOR_CONTEXT.md):

  • 转换节点的透传选项:Edit Fields 开启includeOtherFields;Code 节点显式返回binary: $input.item.binary。有现成选项时这是最便宜的修复。
  • 扇出 + 按位置合并:把源同时路由进转换分支和旁路分支,再用combineByPosition模式的 Merge 重新组合。JSON 来自转换侧,二进制在旁路侧原样幸存:
[Source with binary] ─┬─→ [Edit Fields: change JSON] ─┐ │ (binary stripped here) │ │ ├─→ [Merge: combineByPosition] ─→ [Email: attach] │ │ └──────────────────────────────────┘ (bypass — binary passes through untouched)

用 n8n-mcp 的n8n_update_partial_workflow接线时,combineByPosition会按位置把输入 1 的第 N 个 item 与输入 2 的第 N 个 item 配对,因此两条分支的 item 顺序与数量必须对齐。注意两个容易踩的细节:Merge 默认只有2 个输入(接 3+ 分支必须调高输入数,否则多余分支被静默丢弃);连接输入索引是0 基的(旁路分支落在targetInput: 1)。Merge 的字段名(modecombineBynumberOfInputs)在不同版本间有变动,提交结构前用get_node核对nodes-base.merge

如果剥落点太多,逐个 Merge 的成本会超过收益,此时更优解是尽早上传(字节一出现就上传对象存储,URL/key 作为纯 JSON 穿越所有转换,只在需要的节点重新拉取)或把二进制工作推入子工作流(注意 Execute Workflow Trigger 默认的 typed-input 模式只携带命名 JSON 字段、会丢弃$binary,子工作流需要直接收字节时要用 passthrough 输入模式)。


结语

从插槽形态到消费节点、从 Code 节点读写到 mime 契约、从大小限制到执行排查,$binary的完整链路其实只有一条主线:生产者命名、消费者引用、转换节点透传、执行记录验证。记住两句话即可覆盖绝大多数场景——文件内容永远在$binary而不在$json;任何只返回json的节点都在默默丢弃文件。更进一步的边界场景(Agent 工具只能走 JSON、聊天界面必须用 URL 渲染图片)可继续阅读同技能目录下的 AGENT_TOOL_BINARY.md 与 CDN_REQUIREMENT.md。

【免费下载链接】n8n-mcpA MCP for Claude Desktop / Claude Code / Windsurf / Cursor to build n8n workflows for you项目地址: https://gitcode.com/GitHub_Trending/n8/n8n-mcp

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

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

CNSH-Editor:开源文件模板引擎与配置管理实战解析

做这个系统的直接原因&#xff1a;模板文件失控带来的维护成本说起来你可能不信&#xff0c;CNSH-Editor v1.0 最早不是"设计"出来的&#xff0c;而是被一堆乱七八糟的模板文件逼出来的。当时我在维护一个中等规模的开源项目&#xff0c;里面各种模板散落得到处都是&…

作者头像 李华
网站建设 2026/9/13 4:11:38

EKF、UKF与粒子滤波:非线性状态估计的实战对比与Matlab实现

从实际项目里第一次接触卡尔曼滤波&#xff0c;到后来把EKF、UKF、粒子滤波挨个在Matlab里撸了一遍&#xff0c;这个过程我走了不少弯路。最开始拿标准KF套一个强非线性系统&#xff0c;发散到连曲线都画不出来&#xff0c;折腾很久才明白问题的根源在哪儿。所以这次我不打算堆…

作者头像 李华
网站建设 2026/9/13 4:10:20

时间复杂度与渐进分析:大O、大Ω、大Θ从入门到实战判断

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

作者头像 李华
网站建设 2026/9/13 4:09:21

.NET日志框架核心原理与实现实战

1. .NET日志框架核心原理剖析日志系统是现代应用程序不可或缺的组成部分&#xff0c;它如同飞机的黑匣子&#xff0c;记录着程序运行时的关键信息。在.NET生态中&#xff0c;日志框架的设计哲学主要体现在以下几个核心维度&#xff1a;1.1 日志分级机制.NET日志系统采用分级设计…

作者头像 李华
网站建设 2026/9/13 4:09:15

Linux rlogin命令详解:远程登录工具的基本用法与安全实践

1. rlogin命令概述与基本用法rlogin&#xff08;Remote Login&#xff09;是Linux系统中用于远程登录的传统工具&#xff0c;它允许用户通过网络连接到另一台Unix/Linux主机并启动交互式会话。这个命令诞生于早期的BSD Unix系统&#xff0c;至今仍在许多场景下发挥作用。1.1 命…

作者头像 李华