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:
- `enctype="multipart/form-data"` β without it, the browser only submits the filename, not the file content. Always set this on forms with file inputs.
- `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.