{
  "name": "Учебное кодирование файла в Base64",
  "active": false,
  "nodes": [
    {
      "id": "manual",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        260
      ],
      "parameters": {}
    },
    {
      "id": "sample-text",
      "name": "Sample Text",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        220,
        260
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "return [{ json: { text: \"Привет, n8n!\\n\" } }];"
      }
    },
    {
      "id": "make",
      "name": "Make File",
      "type": "n8n-nodes-base.convertToFile",
      "typeVersion": 1.1,
      "position": [
        440,
        260
      ],
      "parameters": {
        "operation": "toText",
        "sourceProperty": "text",
        "binaryPropertyName": "document",
        "options": {
          "fileName": "file-base64-demo.txt",
          "encoding": "utf8",
          "addBOM": false
        }
      }
    },
    {
      "id": "check-file",
      "name": "Check File",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        660,
        260
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const items = $input.all();\nif (items.length !== 1) throw new Error('one_file_required');\nconst source = $('Sample Text').first().json;\nif (Object.keys(source).join('|') !== 'text' || typeof source.text !== 'string' ||\n    !source.text.trim() || !source.text.isWellFormed() || source.text.includes('\\u0000')) {\n  throw new Error('source_text_invalid');\n}\nconst item = items[0];\nif (Object.keys(item.binary ?? {}).join('|') !== 'document') throw new Error('document_required');\nconst meta = item.binary.document;\nif (meta.fileName !== 'file-base64-demo.txt' || meta.mimeType !== 'text/plain') throw new Error('file_metadata_invalid');\nconst bytes = await this.helpers.getBinaryDataBuffer(0, 'document');\nif (bytes.length < 1 || bytes.length > 4096) throw new Error('file_size_invalid');\nif (!bytes.equals(Buffer.from(source.text, 'utf8'))) throw new Error('source_bytes_mismatch');\nreturn [{ json: {\n  file_name: meta.fileName, mime_type: meta.mimeType, source_bytes: bytes.length\n}, binary: item.binary }];"
      }
    },
    {
      "id": "encode",
      "name": "Encode File",
      "type": "n8n-nodes-base.extractFromFile",
      "typeVersion": 1.1,
      "position": [
        880,
        260
      ],
      "parameters": {
        "operation": "binaryToPropery",
        "binaryPropertyName": "document",
        "destinationKey": "file_base64",
        "options": {
          "keepSource": "both"
        }
      }
    },
    {
      "id": "check-base64",
      "name": "Check Base64",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1100,
        260
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const items = $input.all();\nif (items.length !== 1 || !items[0].binary?.document) throw new Error('source_binary_required');\nconst item = items[0], row = item.json;\nconst value = row.file_base64;\nconst bytes = await this.helpers.getBinaryDataBuffer(0, 'document');\nif (typeof value !== 'string' || value !== bytes.toString('base64')) throw new Error('base64_mismatch');\nif (row.source_bytes !== bytes.length || row.file_name !== 'file-base64-demo.txt' || row.mime_type !== 'text/plain') {\n  throw new Error('source_metadata_missing');\n}\nif (value.length !== 4 * Math.ceil(bytes.length / 3)) throw new Error('base64_length_mismatch');\nreturn [{ json: {\n  file_name: row.file_name, mime_type: row.mime_type,\n  source_bytes: row.source_bytes, file_base64: value\n}, binary: item.binary }];"
      }
    },
    {
      "id": "restore",
      "name": "Restore File",
      "type": "n8n-nodes-base.convertToFile",
      "typeVersion": 1.1,
      "position": [
        1320,
        260
      ],
      "parameters": {
        "operation": "toBinary",
        "sourceProperty": "file_base64",
        "binaryPropertyName": "restored",
        "options": {
          "fileName": "={{$json.file_name}}",
          "mimeType": "={{$json.mime_type}}",
          "addBOM": false
        }
      }
    },
    {
      "id": "check-restored",
      "name": "Check Restored",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1540,
        260
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const items = $input.all();\nif (items.length !== 1 || Object.keys(items[0].binary ?? {}).join('|') !== 'restored') {\n  throw new Error('restored_file_required');\n}\nconst item = items[0], source = $('Check Base64').first().json;\nconst meta = item.binary.restored;\nif (meta.fileName !== source.file_name || meta.mimeType !== source.mime_type) throw new Error('restored_metadata_mismatch');\nconst bytes = await this.helpers.getBinaryDataBuffer(0, 'restored');\nconst expected = Buffer.from($('Sample Text').first().json.text, 'utf8');\nif (!bytes.equals(expected) || bytes.toString('base64') !== source.file_base64) throw new Error('restored_bytes_mismatch');\nreturn [{ json: {\n  file_name: meta.fileName, source_bytes: bytes.length, base64_chars: source.file_base64.length,\n  file_base64: source.file_base64, verified: true, action_performed: false\n}, binary: item.binary }];"
      }
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Sample Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sample Text": {
      "main": [
        [
          {
            "node": "Make File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Make File": {
      "main": [
        [
          {
            "node": "Check File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check File": {
      "main": [
        [
          {
            "node": "Encode File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Encode File": {
      "main": [
        [
          {
            "node": "Check Base64",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Base64": {
      "main": [
        [
          {
            "node": "Restore File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Restore File": {
      "main": [
        [
          {
            "node": "Check Restored",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  }
}
