Tips > Data, APIs & Webhooks

Handle Multipart Form Data and File Uploads via Webhooks

The Webhook node can receive file uploads sent as multipart form data.

TipIntermediate2 min read

The Webhook node can receive file uploads sent as multipart form data. n8n automatically converts uploaded files into binary data attached to the incoming item. You can then process these files downstream -- resize images, parse CSVs, store them in S3, or attach them to emails.

Real-world example: A web form lets users upload a profile photo. The form POSTs to your n8n webhook, which resizes the image and stores it in S3.

Webhook node configuration:

{
  "httpMethod": "POST",
  "path": "uploads/profile-photo",
  "responseMode": "responseNode",
  "options": {
    "binaryData": true,
    "rawBody": true
  }
}
```text
The incoming data structure after a file upload:

```json
{
  "headers": {
    "content-type": "multipart/form-data; boundary=..."
  },
  "body": {
    "username": "jdoe",
    "email": "jdoe@example.com"
  },
  "binary": {
    "file0": {
      "fileName": "photo.jpg",
      "fileType": "image/jpeg",
      "fileSize": 245678,
      "data": "<base64-encoded-data>"
    }
  }
}
```text
Process the uploaded file in a Code node:

```javascript
// Code node: "Validate Upload"
const binary = $input.first().binary;
const formData = $input.first().json.body;

if (!binary || !binary.file0) {
  return [{
    json: {
      error: 'No file uploaded',
      statusCode: 400
    }
  }];
}

const file = binary.file0;
const allowedTypes = ['image/jpeg', 'image/png', 'image/webp'];
const maxSize = 5 * 1024 * 1024; // 5MB

if (!allowedTypes.includes(file.mimeType)) {
  return [{
    json: {
      error: `File type ${file.mimeType} not allowed`,
      statusCode: 400
    }
  }];
}

if (file.fileSize > maxSize) {
  return [{
    json: {
      error: 'File exceeds 5MB limit',
      statusCode: 400
    }
  }];
}

return [{
  json: {
    username: formData.username,
    fileName: file.fileName,
    fileType: file.mimeType,
    fileSize: file.fileSize,
    statusCode: 200
  },
  binary: { file0: binary.file0 }
}];
```text
Then connect an S3 node or HTTP Request node to upload the binary data to your storage service. The binary data passes through the workflow automatically as long as each node preserves it.

**Related:** [Set a Unique Encryption Key and Back It Up](../security-best-practices/01-set-a-unique-encryption-key-and-back-it-up.md) | [Use the HTTP Request Node as a Universal Connector](../integration-patterns/01-use-the-http-request-node-as-a-universal-connector.md)

Want this running in your stack?

I build production n8n and Cloudflare automation for teams — the same engineering behind HarperFlow. Fixed-price, escrow-protected, US-based.