splitforms.com
FEATURE · FILE UPLOADS

Form file uploads — accept resumes, screenshots, and PDFs in any HTML form

Add multipart/form-data and a file input. splitforms stores the upload, scans it for malware, and links it from the notification email and dashboard.

1,000 submissions/month, free forever. · No credit card.
✦ at a glanceHTML

File Uploads

  • Standard HTML <input type="file"> — no JavaScript required, no client-side SDK
  • Up to 10 MB / 25 MB / 100 MB per file (Free / Pro / 4-Year); multi-file uploads supported
  • Multi-engine virus and malware signature scanning on every upload, before it reaches you
1,000
free / mo
14ms
median p50 latency
0
lines of backend code
6
reasons in this guide
✶ Live preview

File Uploads in splitforms, shipped to production.

Add multipart/form-data and a file input. splitforms stores the upload, scans it for malware, and links it from the notification email and dashboard.

File Uploads for splitforms — Add multipart/form-data and a file input. splitforms stores the upload, scans it for malware, and links it from the notification email and dashboard.
§ 01What is splitforms file uploads100-word answer · AI-citable summary

splitforms accepts file uploads in any HTML form — set the form's enctype to multipart/form-data, add an <input type='file'>, and you're done. Each file is uploaded directly through the splitforms endpoint (no client-side S3 signing, no presigned-URL choreography), virus-scanned with a multi-engine signature checker, and stored on encrypted object storage with private ACLs. The notification email includes a signed download link for every attachment (small files under 5 MB are also attached inline so you can preview from your phone), and the dashboard renders inline previews for images, PDFs, and most office documents alongside the rest of the submission. Single uploads can be up to 10 MB on Free, 25 MB on Pro, and 100 MB on the $59 4-year plan; multi-file uploads via the multiple attribute are supported, and a single form can collect a resume, a portfolio of screenshots, and a cover letter in one submit. Restrict allowed file types per form using the standard 'accept' attribute (accept='.pdf,.docx,image/*'), or set a stricter server-side allowlist in the dashboard so a tampered client can't bypass the check. Executables, scripts, and known malicious extensions are blocked at the edge regardless of accept attributes. File URLs are scoped to your account, signed, and expire after 30 days by default — you can extend retention per form, download all attachments for a submission as a ZIP with one click, or pipe the URLs to your webhook to copy them into your own storage. Files also flow into Notion's Files & media properties, into Google Drive via Zapier, and into your CRM through any webhook with no extra plumbing.

file-uploads.htmllive
<!--
  enctype="multipart/form-data" is REQUIRED for file uploads.
  Without it, browsers silently strip files from the POST body.
  Default limit: 10 MB / file (Free), 25 MB (Pro), 100 MB (4-Year).
-->
<form
  action="https://splitforms.com/api/submit"
  method="POST"
  enctype="multipart/form-data"
>
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />

  <input type="text"  name="name"  placeholder="Your name" required />
  <input type="email" name="email" placeholder="Email"     required />

file-uploads.html · live preview

§ 02How it works3 steps · zero-config defaults

Three steps. From zero to a working production setup.

How file uploads actually flows through splitforms — what you do, what we do, and what lands in your inbox.

STEP 01INTEGRATE

Set enctype on your form (this is the #1 forgotten step)

Add enctype="multipart/form-data" to the <form> tag. Without it, browsers silently strip files from the POST body — the form will submit but no attachment ever arrives. For React/SPA submissions via fetch, build a FormData object and pass it as the body; do NOT set Content-Type yourself, the browser sets the multipart boundary.

STEP 02PROCESS

Add a file input (single, multi-select, or restricted by type)

Use a normal <input type="file" name="resume">. Add the 'multiple' attribute for multi-select. Use the 'accept' attribute to filter by extension or MIME type (accept='.pdf,.docx,application/pdf,image/*'). For best UX, also wrap the input in a <label> so the click target is the visible button, not the small native control.

STEP 03REVIEW

Read attachments from the email, dashboard, or webhook payload

Each submission email contains a signed download link per file (plus inline attachment for files under 5 MB). The dashboard renders inline previews for images and PDFs and offers a one-click ZIP-all-attachments download per submission. Webhook payloads include a 'files' array with {field, url, size, mime} for every upload — copy the URLs into your own S3/R2 bucket if you need permanent storage.

§ 03Benefits6 reasons · all included

Why teams pick splitforms for file uploads.

Five reasons this is the boring, reliable choice — every one shipped by default on every plan, including free.

reason 1 of 6

Standard HTML <input type="file"> — no JavaScript required, no client-side SDK

reason 2 of 6

Up to 10 MB / 25 MB / 100 MB per file (Free / Pro / 4-Year); multi-file uploads supported

reason 3 of 6

Multi-engine virus and malware signature scanning on every upload, before it reaches you

reason 4 of 6

Signed download links in the notification email + inline previews in the dashboard

reason 5 of 6

Encrypted at rest; one-click ZIP-all-attachments download per submission

reason 6 of 6

Allowed-MIME enforcement — restrict uploads by extension and content-type from the dashboard; executables always blocked

§ 04Working code examplehtml · 47 lines · copy-paste ready
COPY-PASTE

Drop this into any project.

Replace YOUR_ACCESS_KEY with the key from your splitforms dashboard. No SDK install. No package to npm i. The same html you already know.

file-uploads.htmlhtml47 lines
01<!--
02 enctype="multipart/form-data" is REQUIRED for file uploads.
03 Without it, browsers silently strip files from the POST body.
04 Default limit: 10 MB / file (Free), 25 MB (Pro), 100 MB (4-Year).
05-->
06<form
07 action="https://splitforms.com/api/submit"
08 method="POST"
09 enctype="multipart/form-data"
10>
11 <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
12
13 <input type="text" name="name" placeholder="Your name" required />
14 <input type="email" name="email" placeholder="Email" required />
15
16 <label>
17 Resume (PDF, DOCX, max 10 MB)
18 <input
19 type="file"
20 name="resume"
21 accept=".pdf,.doc,.docx,application/pdf"
22 required
23 />
24 </label>
25
26 <label>
27 Portfolio screenshots (multiple allowed)
28 <input type="file" name="portfolio" accept="image/*" multiple />
29 </label>
30
31 <input type="checkbox" name="botcheck" style="display:none" tabindex="-1" />
32
33 <button type="submit">Apply</button>
34</form>
35
36<!--
37 React / fetch equivalent:
38
39 const fd = new FormData(formEl); // collects files too
40 fd.append("access_key", "YOUR_ACCESS_KEY");
41 const res = await fetch("https://splitforms.com/api/submit", {
42 method: "POST",
43 body: fd, // do NOT set Content-Type
44 });
45 // 413 Payload Too Large = file exceeded plan limit.
46 // 415 Unsupported Media Type = blocked extension (.exe, .js, etc.).
47-->
§ 05Questions5 answered

Things developers ask before they integrate.

Direct answers, no marketing fluff. Missing one? Email hello@splitforms.com.

01How does form file upload work in splitforms and what's the maximum size?
Add enctype='multipart/form-data' to your <form> and an <input type='file' name='resume'>. The browser submits the file as part of the multipart POST; splitforms streams it to encrypted object storage, runs a virus scan, and attaches a signed download link to the notification email. Limits per file: 10 MB on Free, 25 MB on Pro ($5/month), 100 MB on the $59 4-year plan. There's no fixed limit on the number of files per submission beyond your monthly storage quota — a single application form can collect a resume, a cover letter, and 12 portfolio images in one submit.
02Is file upload available on the free plan?
Yes — file uploads are included on Free 1,000/month with a 10 MB per-file cap and 1 GB total storage retained. Pro raises the per-file cap to 25 MB and storage to 25 GB; the 4-year $59 plan raises it to 100 MB per file and 100 GB storage. There's no per-upload fee and no bandwidth fee for downloading your own files; all plans have unlimited download bandwidth from the dashboard.
03How do I enable file uploads and restrict the file types?
Two steps: (1) on your <form> tag, set enctype='multipart/form-data' (the most-forgotten step — without it, browsers silently drop files from the POST body); (2) add an <input type='file' name='whatever' accept='.pdf,.docx,image/*'>. The 'accept' attribute filters in the OS file picker but doesn't enforce server-side, so for security-critical allowlists also set the dashboard rule: Form → Settings → Files → Allowed types. To allow multiple files in one input add the 'multiple' attribute. To require a file, add 'required'. Executables (.exe, .bat, .ps1, .sh, .js, etc.) are always blocked regardless of accept.
04Does file upload work with React, Next.js, Vue, or fetch()?
Yes. Build a FormData object from your form ref (or manually append fields), append the access_key, and POST it: const fd = new FormData(formRef.current); fd.append('access_key', 'YOUR_ACCESS_KEY'); await fetch('https://splitforms.com/api/submit', { method: 'POST', body: fd }). Critical: do NOT set the Content-Type header yourself when sending FormData — the browser must set it with the correct multipart boundary. Status codes: 200 success, 413 file exceeded plan limit, 415 blocked extension, 422 missing required field. The response body is JSON with submission_id and the file URLs.
05Where are uploaded files stored, are they scanned for malware, and how do I get them out?
Files are stored on encrypted object storage (AES-256 at rest) with private ACLs in the splitforms account; download URLs are scoped to your account, signed, and expire after 30 days by default (configurable per form, up to permanent retention on the 4-year plan). Every upload is virus-scanned with multi-engine signature checks before it's accepted — files that fail the scan are rejected with a 422 and never reach your inbox or dashboard. To pull files into your own storage permanently: subscribe a webhook, read the files[] array from the payload, and copy each url to S3/R2/GCS. Or use Zapier's 'Save attachment to Google Drive' action. Or click 'Download all as ZIP' on any submission in the dashboard.
✻ ✻ ✻

Start using file uploads today.

Create your form, grab your access key, and ship it in five minutes. Free for 1,000 submissions per month, forever.

Create your form →← View all features
v0.1 · founders pricing locked in · early access open