Loading...
Loading...
Compare original and translation side by side
$json$binary$binary$json$json$binary$binary$json$binary$json$binary.<key>$json$json.dataAGENT_TOOL_BINARY.md$binaryCDN_REQUIREMENT.md$binary$json$binary.<key>$json$json.dataAGENT_TOOL_BINARY.md$binaryCDN_REQUIREMENT.md{
"json": { "customerId": 42, "status": "sent" },
"binary": {
"invoice": {
"data": "<base64-encoded bytes>",
"mimeType": "application/pdf",
"fileName": "invoice-42.pdf",
"fileExtension": "pdf"
}
}
}binaryinvoicebinaryPropertyNamedata$binary.data$json$binary{{ $binary.invoice.fileName }}{{ $json.customerId }}multipart/form-data$binary$json.body$json$json.bodyBINARY_BASICS.md{
"json": { "customerId": 42, "status": "sent" },
"binary": {
"invoice": {
"data": "<base64-encoded bytes>",
"mimeType": "application/pdf",
"fileName": "invoice-42.pdf",
"fileExtension": "pdf"
}
}
}binaryinvoicebinaryPropertyNamedata$binary.data$json$binary{{ $binary.invoice.fileName }}{{ $json.customerId }}multipart/form-data$binary$json.body$json$json.bodyBINARY_BASICS.md$binary| Source | How binary appears |
|---|---|
HTTP Request with | Response body lands in |
| Read/Write Files from Disk | File contents read into |
| Storage downloads (S3, Google Drive, Dropbox, etc.) | Downloaded file in |
| Email triggers with attachments | Each attachment arrives in |
| Provider AI media nodes (image/audio gen) | Set |
responseFormatget_nodenodes-base.httpRequest$json$binary$binary| 来源 | 二进制数据的呈现方式 |
|---|---|
设置 | 响应体存入 |
| 从磁盘读取/写入文件 | 文件内容读取到 |
| 存储服务下载(S3、Google Drive、Dropbox等) | 下载的文件存入 |
| 带附件的邮件触发器 | 每个附件都存入 |
| 供应商AI媒体节点(图像/音频生成) | 设置 |
responseFormatget_nodenodes-base.httpRequest$json$binarygetBinaryDataBuffer$binary.<key>.data// Code node, "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, // pass the binary through, or it's gone
}];const text = 'Hello, world!';
return [{
json: { ok: true },
binary: {
report: {
data: Buffer.from(text).toString('base64'),
mimeType: 'text/plain',
fileName: 'report.txt',
fileExtension: 'txt',
},
},
}];[{ json: {...} }]binaryBINARY_BASICS.mdgetBinaryDataBuffer$binary.<key>.data// Code node, "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, // pass the binary through, or it's gone
}];const text = 'Hello, world!';
return [{
json: { ok: true },
binary: {
report: {
data: Buffer.from(text).toString('base64'),
mimeType: 'text/plain',
fileName: 'report.txt',
fileExtension: 'txt',
},
},
}];[{ json: {...} }]binaryBINARY_BASICS.md$binaryincludeOtherFieldsbinary: $input.item.binarycombineByPosition[Source with binary] ─┬─→ [Edit Fields: change JSON] ─┐
│ (binary stripped here) ├─→ [Merge: combineByPosition] ─→ [Email: attach]
└──────────────────────────────────┘
(bypass — binary passes through untouched)combineByPositionMERGE_FOR_CONTEXT.md$binaryincludeOtherFieldsbinary: $input.item.binarycombineByPosition[Source with binary] ─┬─→ [Edit Fields: change JSON] ─┐
│ (binary stripped here) ├─→ [Merge: combineByPosition] ─→ [Email: attach]
└──────────────────────────────────┘
(bypass — binary passes through untouched)combineByPositionMERGE_FOR_CONTEXT.mdfiles[]executeOnce: true{ "ok": true, "key": "...", "url": "https://...", "mimeType": "image/png" }passthroughBinaryImages: trueAGENT_TOOL_BINARY.mdBuilding the tool itself? See n8n-code-tool for the Custom Code Tool contract and n8n-workflow-patterns for the AI-Agent-with-tools shape.
files[]executeOnce: true{ "ok": true, "key": "...", "url": "https://...", "mimeType": "image/png" }passthroughBinaryImages: trueAGENT_TOOL_BINARY.mdBuilding the tool itself? See n8n-code-tool for the Custom Code Tool contract and n8n-workflow-patterns for the AI-Agent-with-tools shape.
$binaryCDN_REQUIREMENT.md$binaryCDN_REQUIREMENT.md$fromAI()getBinaryDataBuffer$fromAI()getBinaryDataBuffern8n_manage_datatablen8n_manage_datatable| Anti-pattern | What goes wrong | Fix |
|---|---|---|
Reading file contents from | Bytes live in | Read |
HTTP download without | Bytes arrive as mangled text in | Set |
Code node returns | The file is silently dropped downstream | Re-attach |
| JSON transform (Edit Fields/IF) eats the binary | Email/upload node finds nothing to attach | Pass-through option, or fan out + Merge by position |
Passing an uploaded file into a tool via | | Pre-stage to storage, inject the key in the system prompt, tool fetches by key |
Assuming | It only affects what the LLM sees, and only for images | Still need the upload-and-pass-key pattern for tools |
| Tool returns raw binary to the agent | Tool output is JSON; bytes don't survive (and bloat context) | Upload, return |
Posting | Chat clients render by URL, not raw bytes | Upload to storage/CDN, embed the URL or use the platform file API |
| Hardcoding base64 in a Code node | Huge workflow JSON, slow, leaky | Reference via |
| 反模式 | 问题所在 | 修复方案 |
|---|---|---|
从 | 字节数据存储在 | 读取 |
HTTP下载未设置 | 字节数据以乱码文本形式出现在 | 在HTTP请求节点设置 |
Code节点返回 | 文件在下游被静默丢失 | 在返回时重新附加 |
| JSON转换(编辑字段/IF)移除二进制数据 | 邮件/上传节点找不到可附加的文件 | 使用传递选项,或分支输出 + 按位置合并 |
通过 | | 预存到存储服务,在系统提示词中注入密钥,工具通过密钥获取文件 |
认为 | 它仅影响LLM的视觉输入,且仅适用于图片 | 工具仍需使用上传并传递密钥的模式 |
| 工具向Agent返回原始二进制数据 | 工具输出为JSON;字节数据无法保留(且会膨胀上下文) | 上传到存储服务,返回 |
将 | 聊天客户端通过URL渲染,而非原始字节数据 | 上传到存储/CDN,嵌入URL或使用平台文件API |
| 在Code节点中硬编码base64 | 工作流JSON体积庞大、运行缓慢、易泄露 | 通过 |
| File | Read when |
|---|---|
| First time handling binary, or reading/writing the |
| An agent tool needs an uploaded file, or produces one — the boundary in either direction |
| Binary disappears after a JSON transform and you need to re-attach it |
| Showing images in a chat surface or anywhere that needs URL-referenced images |
| 文件 | 阅读场景 |
|---|---|
| 首次处理二进制数据,或读写 |
| Agent工具需要处理上传文件或生成文件——双向边界场景 |
| JSON转换后二进制数据丢失,需要重新附加 |
| 在聊天界面或其他需要URL引用图片的场景显示图片 |
getBinaryDataBufferBuffer.from(...).toString('base64')$binarygetBinaryDataBuffer$fromAIresponseFormatbinaryPropertyNameincludeOtherFieldsbinaryPropertyOutputget_node$binary.<key>.fileName$json.bodyvalidate_workflown8n_manage_datatablen8n_executionsbinarygetBinaryDataBufferBuffer.from(...).toString('base64')$binarygetBinaryDataBuffer$fromAIresponseFormatbinaryPropertyNameincludeOtherFieldsbinaryPropertyOutputget_node$binary.<key>.fileName$json.bodyvalidate_workflown8n_manage_datatablen8n_executionsbinaryn8n_test_workflown8n_executionsbinarybinaryn8n_test_workflown8n_executionsbinarybinary$binary.<key>$jsonresponseFormat: "file"binarycombineByPositionpassthroughBinaryImages$json$binary$binary.<key>$jsonresponseFormat: "file"binarycombineByPositionpassthroughBinaryImages$json$binary