File uploads are the heaviest thing you can add to a form. The HTML is three attributes; everything after the HTML — receiving, storing, scanning, size limits, abuse — is real infrastructure. Here's the markup done right, what must be true at the receiving end, and the lighter pattern that often serves a small business better.
<form action="…" method="POST" enctype="multipart/form-data">
<label for="cv">Your CV (PDF)</label>
<input id="cv" name="cv" type="file" accept=".pdf,application/pdf">
…
</form>
The one everyone forgets: enctype="multipart/form-data"
on the form tag. Without it the browser sends only the file's
name — the classic "the upload arrives empty" bug.
accept filters the file picker (it's a convenience, not
security), and multiple allows several files.
An upload is only as real as the endpoint behind it. Whatever receives the form must be built to accept file parts, enforce size and type limits server-side (the accept attribute is advisory — anything can be posted), store files somewhere with enough space, and take on the abuse duty: an open upload endpoint will be found and fed junk, and files people send you can carry anything. That's why uploads are a paid or premium feature at most form services — the storage and the moderation burden are real costs.
Honest note about our own endpoint: hform currently accepts text fields only — a file attached to a form posting to hform is ignored, not stored. That's deliberate for now, and the pattern below is what we recommend instead.
<label for="cv_link">Link to your CV or portfolio</label>
<input id="cv_link" name="cv_link" type="url"
placeholder="https://…">
Most people who have a file to share already have it in a cloud drive, a portfolio site or a public profile. A link field gets you the same document with none of the infrastructure: nothing to store, nothing to scan, no size limits, and the sender keeps control of their file. For job applications, quotes with reference photos and portfolio reviews, this is usually the better trade — and if a visitor has no link, your reply email is a fine place to receive an attachment.
Some workflows genuinely do — print shops receiving artwork, agencies collecting assets. Then pick infrastructure honestly built for it: a form service whose plan explicitly includes file storage, or your own endpoint with strict server-side limits, virus scanning and a retention plan for the files (uploaded files are personal data too — the retention guide applies).
The form tag is missing enctype="multipart/form-data". Without it the browser submits only the file’s name as text. It’s the single most common file-upload bug.
No — it only filters the visitor’s file picker. Anyone can post any file to your endpoint directly, so type and size limits must be enforced at the receiving end. Treat accept as UX, never as security.
Not currently — the endpoint accepts text fields only, and attached files are ignored rather than stored. Use a link field for documents (it covers most cases with less friction), or receive attachments in your reply email.
The hform builder writes this kind of HTML for you — real labels, the right input types, a honeypot, validation that respects your visitors. Build a form in two minutes; free plan included, plain pricing beyond it.
More form craft: Validation · Phone fields · Form length — or see all guides.