Form ending multiple files

Describe the problem/error/question

I have a form that acceps multiple different files (csv) modifies each a bit and then end the forms and allow those multiple files to be downloaded after modification. Ideally this would happend with each file as optional.

What is the error message (if any)?

Please share your workflow

(Select the nodes on your canvas and use the keyboard shortcuts CMD+C/CTRL+C and CMD+V/CTRL+V to copy and paste the workflow.)
{
  "nodes": [
    {
      "parameters": {
        "formTitle": "test",
        "formDescription": "test",
        "formFields": {
          "values": [
            {
              "fieldLabel": "test 1",
              "fieldType": "file"
            },
            {
              "fieldLabel": "test 2",
              "fieldType": "file"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.formTrigger",
      "typeVersion": 2.5,
      "position": [
        0,
        0
      ],
      "id": "3a52abab-7c0a-4bb5-9ca1-8d0de459c753",
      "name": "On form submission",
      "webhookId": "78bd5f75-3e6a-41f7-ac02-53877b82819d"
    },
    {
      "parameters": {
        "operation": "completion",
        "respondWith": "returnBinary",
        "completionTitle": "finish test",
        "inputDataFieldName": "={{ Object.keys($binary).join(',') }}",
        "options": {}
      },
      "type": "n8n-nodes-base.form",
      "typeVersion": 2.5,
      "position": [
        912,
        32
      ],
      "id": "f0732486-1f0d-4e11-afc4-e67a99d99776",
      "name": "Form",
      "webhookId": "43959bca-7a44-4839-98a8-f900bd974d11"
    },
    {
      "parameters": {
        "operation": "text",
        "binaryPropertyName": "test_1",
        "options": {}
      },
      "type": "n8n-nodes-base.extractFromFile",
      "typeVersion": 1.1,
      "position": [
        208,
        -64
      ],
      "id": "3ea1c229-6a3b-4688-8eeb-95599a80bd44",
      "name": "Extract from File"
    },
    {
      "parameters": {
        "operation": "text",
        "binaryPropertyName": "test_2",
        "options": {}
      },
      "type": "n8n-nodes-base.extractFromFile",
      "typeVersion": 1.1,
      "position": [
        208,
        112
      ],
      "id": "302af422-d73c-4c3e-84fd-abd239774622",
      "name": "Extract from File1"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.2,
      "position": [
        480,
        32
      ],
      "id": "567aded2-d59e-4d62-b6d4-12315ebf57d1",
      "name": "Merge"
    },
    {
      "parameters": {
        "jsCode": "const items = $input.all();\n\nconst binary = {};\nitems.forEach((item, i) => {\n  const key = Object.keys(item.binary)[0];\n  binary[`data${i + 1}`] = item.binary[key];\n});\n\nreturn [{ json: {}, binary }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        688,
        32
      ],
      "id": "bfaaa64a-7477-4b91-8abe-bd081842a135",
      "name": "Code in JavaScript"
    }
  ],
  "connections": {
    "On form submission": {
      "main": [
        [
          {
            "node": "Extract from File1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Extract from File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract from File": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract from File1": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Form",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "meta": {
    "instanceId": "cf4367492d34bb4e3c07a58320944bd2f74a2f520740b248009864d36f47bda6"
  }
}

Share the output returned by the last node

No binary data with field data1,data2 found.

Information on your n8n setup

  • n8n version: 2.17.4
  • Database (default: SQLite): sqlite
  • n8n EXECUTIONS_PROCESS setting (default: own, main): default
  • Running n8n via (Docker, npm, n8n cloud, desktop app): npm
  • Operating system: debian 13

Hi @CrazyWolf13 Welcome!
You either need to convert your files into a zip before sending it to the ending form for multiple files, OR i have did some coding on that javascript , and this below workaround should really help you in all the cases:

Let me know how this goes.

Hi @Anshul_Namdev

Appreciate your reply!

I have copied the above code, but unfortunately it’s the same, on form end it still only downloads one binary (the first of the array).

ZIP- based is working so far, but it adds unneccessary overhead and makes the process tedious to always have to unzip them and delte the archive and extra folder again.

@CrazyWolf13 i think then ZIP or via using the WEBHOOK with custom HTML would be a better take. As that would be more reliable.

@CrazyWolf13 the Form completion node just doesn’t support multiple binaries with returnBinary, that’s a known limitation. skip it entirely — switch to respondWith: "text" and use a Code node to build data-URI download links for each file, the completion message renders HTML so each file gets its own clickable link

just wire this after your Merge node instead of your current Code + Form nodes, each CSV gets its own download link on the completion page

Thank you both!

@Anshul_Namdev How would that work with webhooks?

@achamm thanks! that looks promising!!
however with your code I did not get it to work, first “Show completion message” does not seem to render html at all, so after switching to “Show Text“ it displays the actual html, however the download does not seem to work:

Any ideas?

Thanks!

@CrazyWolf13 the HTML is rendering fine, the actual problem is $binary[key].data returns filesystem-v2 (a storage ref) instead of real base64 on newer n8n — you need await this.helpers.getBinaryDataBuffer() to read actual file content. replace your Code + Form nodes with this:

wire Merge output into “Build Download Links”, the getBinaryDataBuffer call fetches the real file bytes from n8n’s filesystem storage so the data URIs actually contain your CSV data

Thanks a lot, working fine now!