Skip to main content
← πŸ“„ HTML & the platformΒ·Module A3 Β· Lesson 10
TaskBuild an upload form: enctype='multipart/form-data', method='post', action='/api/upload'. <input type='file' name='photo' accept='image/*'>, <input type='file' name='docs' multiple accept='.pdf'>, submit button.

<input type=file>: uploads + multipart

100 XP8 min
Theory

File uploads need multipart enctype

<form action="/api/upload" method="post" enctype="multipart/form-data">
  <input type="file" name="avatar" />
  <input type="file" name="docs" multiple accept=".pdf,.docx" />
  <button type="submit">Upload</button>
</form>

Two changes vs a regular form:

  1. `enctype="multipart/form-data"` β€” without it, the browser only submits the filename, not the file content. Always set this on forms with file inputs.
  2. `accept=…` on the file input β€” restricts the OS picker to matching files. Either MIME types (image/png) or extensions (.pdf).

multiple

<input multiple> lets the user pick more than one file at once. Submitted as repeated form keys (same name, multiple files).

Accept patterns

<input type="file" accept="image/*" />              <!-- any image MIME -->
<input type="file" accept=".jpg,.png,.webp" />      <!-- specific extensions -->
<input type="file" accept="image/png,image/jpeg" /> <!-- specific MIMEs -->
<input type="file" accept="application/pdf" />

accept is a HINT β€” browsers honor it loosely. Backend MUST re-validate by reading the actual file content (magic bytes), not just the extension.

FastAPI side

from fastapi import UploadFile

@app.post("/api/upload")
async def upload(avatar: UploadFile, docs: list[UploadFile] = []):
    return {"avatar": avatar.filename, "docs": [d.filename for d in docs]}

The form's name="avatar" becomes the function arg. multiple becomes list[UploadFile].

πŸ”’

Sign up to start coding

Theory is open to everyone. The interactive editor, live preview, and check are unlocked with a 7-day free trial β€” card required, cancel anytime.

Sign up β€” free trial β†’

First 10 lessons in each track are free. No card needed for those.

← PreviousNext lesson β†’

Get one Python or web tip a day β€” by email

Short, hand-written, no spam. Unsubscribe in one click.