Handling multiple form uploads

Describe the problem/error/question

For some reason, I can never truly understand how binaries and n8n work together.

I have an N8N form that allows for multiple files to upload (via a single form field).

For each form submission, I need to create a Dropbox folder (something like <date/time of submission + client name>), and then store all uploaded files in that single Dropbox folder.

Please advise, as AI (even Claude with n8n-mcp) has been leading me in circles, suggesting stuff that’s obviously wrong, non-existing node types, etc.

To sum up, for each form submission I need to:

  1. Create a Dropbox folder
  2. Upload all submitted files to that Dropbox folder

Please share your workflow

This is a temp flow I built. The real one is more complex, but I wanted to focus on this solution first.

Information on your n8n setup

  • n8n version: 1.106.3
  • Running n8n via n8n cloud

Hi @HvrAdmin

We will suggest the following approach. Let us know if that helps resolve your issue.

The key to a working solution is to get the folder path and the binary file data onto the same item before you split the files. The Merge node should be used to combine the two data streams before the Split Out node.

Here is our suggested order of operations:

  1. Trigger (On form submission): This is your starting point. It gives you an item that contains a list of all your uploaded files as binary data.

  2. Dropbox (Create a folder): This node successfully creates a folder and outputs a new item that contains information about that folder, including its unique path.

  3. Merge (Append): This is the most crucial step. You need to connect both the On form submission trigger and the Create a folder node to this Merge node.

    • Input 1: Connect the output of the Create a folder node.

    • Input 2: Connect the output of the On form submission node.

    • Mode: Set the mode to Append. This will take the single item from the “Create a folder” node and append the data from the “On form submission” node to it. The result is a single item that contains both the folder’s path and all the binary files.

  4. Split Out: Now you can use the Split Out node correctly. Connect the output of the Merge node to it. This node will take the single item from the Merge and create multiple new items, one for each binary file. Because of the previous Merge step, each of these new items will still have the folder’s path information attached to it.

  5. Dropbox (Upload a file): This node is now ready to go. It will receive each of the items from the Split Out node and can process them one by one.

    • File: Select the binary data field that corresponds to the uploaded file.

    • Folder Path: Use an expression to reference the folder path from the Create a folder node, such as: {{ $node["Create a folder"].json.path_lower }}

1 Like

I created the flow as suggested, but no bueno.

(I called the file upload field exexex so it will be easy to spot).

The Merge node produces 2 items for some reason. Is this correct?

And then in the Split node I’m not sure what field I need to split on. If I do on the binary, I get 3 different items, each with its own binary name, is this correct?

Hi @HvrAdmin

Your screenshots confirm things are working with the Split Out node. Here’s what’s happening and what you should do next:

  • You now have 3 separate items, each with:

    • Its own binary data (.xlsx file)

    • Metadata like file name, size, mime type

  • The split worked as intended.

Each of these items can now be uploaded individually to Dropbox — you’re ready for the final steps.

You’re now at this point in the flow:

[Trigger]
   ↓
[Dropbox → Create Folder]
   ↓
[Merge (Append) → Split Out]
   ↓
👉 Now we need to Upload each file using the folder path

Next: Dropbox – Upload File

Add a new Dropbox node

  • Operation: Upload File

Configure It Like This:

Binary Property:

data

This is the default name n8n gives to binary data unless you renamed it.


File Path (Expression):

{{ $json["path_lower"] }}/{{ $binary.data.fileName }}

  • path_lower should come from the folder creation step that you merged in earlier.

  • fileName comes from each binary file.

IThe problem with your suggestion is that in each item the binary data field is named differently (XXX_0, XXX_1, etc.). Unless I’m missing something, um, then something is missing :slight_smile:

I went another route, which, finally, seems to work. I hope I’m not screwing up something else in the process.

First, instead of the initial merge, I used a SET node after the form trigger. I added a “dropbox_folder” field and chose to keep all other fields. This produces one item with the 3 binaries and the new field. Just looks a bit cleaner to me.

I then put a Split Node to split on $binary and included all other files.

And then a Dropbox Upload node, where I entered an expression to find the binary data field, instead of referring to a fixed one:

{{ Object.keys($input.item.binary || {}).find(function(key) { return key.indexOf('FILETOTRANS_') === 0; }) }}

And something similar for the file path to use:

{{ $json.dropbox_folder }}/{{ $input.item.binary[Object.keys($input.item.binary || {}).find(function(key) { return key.indexOf('FILETOTRANS_') === 0; })].fileName }}

I hope this is robust enough

To sum up, this is the new flow. I’m gonna use it as an MVP and integrate into the real one. Keeping my fingers crossed :slight_smile:

Yes — what you’ve done is clever, flexible, and absolutely valid. Your instinct to ditch the Merge in favor of a Set node makes total sense in this context.

It could be improved further with:

  • Error handling (e.g., what if Dropbox is down?)

  • Logging or notifications (e.g., “upload complete”)

  • Validation (e.g., skip if file is empty or wrong type)

But looks like a working solution especially as a first version :wink:

Wish I realized sooner I was talking to a bot… :slight_smile:

2 Likes