Skip to content
← All use cases
Use case · File upload forms

Accept file uploads on any HTML form

Set enctype="multipart/form-data", add a file input with a name, and point the form at Formward. The files are stored with the submission on servers in Sweden, and you download them from the dashboard.

<form action="https://forms.formward.eu/f/YOUR_FORM_ID"
      method="POST" enctype="multipart/form-data">
  <input type="email" name="email" required>
  <input type="file" name="attachment" accept=".pdf,.jpg,.png" multiple>
  <button type="submit">Send</button>
</form>

Uploads are part of the Professional and Business plans. On Free and Personal the endpoint refuses a submission that carries files, so test on a paid plan before you publish the form.

Size and count limits

PlanFiles per submissionPer filePer submissionStored in total
Professional510 MiB25 MiB2 GiB per workspace
Business1025 MiB25 MiB10 GiB per workspace

The per-submission ceiling is the same on both plans; Business gets larger single files and more of them inside it. The stored total covers every form in the workspace, and deleting submissions frees the space again. Set the accept attribute and a note next to the input so visitors know the limits before they pick a file.

Accepted file types

Formward accepts images (JPEG, PNG, GIF, WebP), PDF, plain text and CSV, Microsoft Office documents (Word, Excel, PowerPoint) and their OpenDocument equivalents. Anything else, including archives, executables, scripts and HTML, is refused with a 415.

Upload with fetch() and show progress in place

new FormData(form) picks up file inputs along with the other fields. On success the JSON response includes the number of files stored.

const form = document.querySelector("form");
form.addEventListener("submit", async (event) => {
  event.preventDefault();
  // Do not set Content-Type yourself: the browser adds the multipart boundary.
  const res = await fetch(form.action, {
    method: "POST",
    headers: { Accept: "application/json" },
    body: new FormData(form),
  });
  const data = await res.json();
  if (res.ok) {
    form.reset();
    form.after(`Received, with ${data.files} file(s).`);
  } else {
    // 413: too large, 415: file type not allowed, 403: uploads not enabled
    alert(data.error);
  }
});

Where the files go

Files are stored with the submission in Sweden, on infrastructure run by Hostup AB, the same as the rest of the submission. They appear in an Attachments section on the submission with their size and type. The notification email links to them rather than carrying them, which keeps CVs and ID photos out of mail archives.

Deleting files on time

Uploaded documents are often the most sensitive part of a submission. Set a retention period on the form, anywhere from 1 to 3,650 days, and the nightly cleanup deletes expired submissions together with their files. If a stored file cannot be removed on the first try, the job keeps retrying it instead of forgetting it. The retention guide suggests periods for common form types.

Where the data lives

Formward stores submissions, file attachments and backups in Sweden, on servers run by Hostup AB. Notification email goes out through Mailjet from an EU data centre. Submitter IP addresses are replaced with a keyed HMAC-SHA-256 hash on receipt, so the raw address is never written to disk. On Professional and Business, AI features run on Mistral AI in France and can be switched off per form.

Data leaves the EU only where you send it: a notification inbox hosted outside the EU, a webhook URL, a Slack channel or a Google Sheet. Cloudflare Turnstile is a US service, and it is off unless you switch it on for a form. The details are in the sub-processor register, the data residency page and the published DPA. For the wider picture, see GDPR form backend.

Questions

Can I accept files on the Free plan?
No. File uploads start on Professional. The rest of the form, including email notifications and spam filtering, works on Free.
Are files attached to the notification email?
No. The email lists each file name and size with a link to the submission, and the download happens in the signed-in dashboard. With the link-only setting the file names are left out too.
What happens when a file is too large?
The whole submission is rejected with a 413 and nothing is stored, so the visitor can try again with a smaller file. A 415 means the file type is not on the allowed list.
Who can download the files?
Members of the workspace that owns the form, through a signed-in dashboard link. HTML, SVG and other non-image files are always served as downloads, so an uploaded file cannot run as a page on the dashboard.

Take uploads on your own form

Professional is EUR 30 a month, or EUR 20 a month billed yearly.

Forms with file uploads, stored in the EU | Formward