Bird
Raised Fist0
FastAPIframework~10 mins

File validation (size, type) in FastAPI - Step-by-Step Execution

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Concept Flow - File validation (size, type)
Receive file upload request
Check file size <= max allowed?
NoReject: File too large
Yes
Check file type in allowed types?
NoReject: Invalid file type
Yes
Accept file and process/save
Response sent
The server receives a file, checks its size and type, rejects if invalid, otherwise accepts and processes it.
Execution Sample
FastAPI
from fastapi import FastAPI, File, UploadFile, HTTPException
app = FastAPI()

@app.post("/upload")
async def upload(file: UploadFile = File(...)):
    if file.content_type not in ["image/png", "image/jpeg"]:
        raise HTTPException(status_code=400, detail="Invalid file type")
    contents = await file.read()
    if len(contents) > 1024 * 1024:
        raise HTTPException(status_code=400, detail="File too large")
    return {"filename": file.filename, "size": len(contents)}
This code checks if the uploaded file is PNG or JPEG and smaller than 1MB, else rejects it.
Execution Table
StepActionCheckResultNext Step
1Receive file uploadN/AFile receivedCheck file type
2Check file typefile.content_type in ['image/png', 'image/jpeg']TrueRead file contents
3Read file contentsN/AFile bytes loadedCheck file size
4Check file sizelen(contents) <= 1048576TrueAccept file
5Accept fileN/AReturn filename and sizeEnd
6Receive file uploadN/AFile receivedCheck file type
7Check file typefile.content_type in ['image/png', 'image/jpeg']FalseReject: Invalid file type
8Reject fileN/ARaise HTTPException 400End
9Receive file uploadN/AFile receivedCheck file type
10Check file typefile.content_type in ['image/png', 'image/jpeg']TrueRead file contents
11Read file contentsN/AFile bytes loadedCheck file size
12Check file sizelen(contents) <= 1048576FalseReject: File too large
13Reject fileN/ARaise HTTPException 400End
💡 Execution stops when file is accepted or rejected due to type or size check failure.
Variable Tracker
VariableStartAfter Step 3After Step 4Final
file.content_typeN/Aimage/png or image/jpeg or otherSameSame
contents (bytes)N/ALoaded bytes of fileSameSame
len(contents)N/AFile size in bytesCompared to 1048576Same
Key Moments - 3 Insights
Why do we check file type before reading contents?
Checking file type first (see execution_table step 2) avoids unnecessary reading of large files if type is invalid.
What happens if file size exceeds the limit?
At step 12 in execution_table, if size is too big, the code raises an HTTPException rejecting the file.
Why do we use await when reading file contents?
Because reading file is asynchronous in FastAPI, await ensures we get the full content before size check (step 3).
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what happens at step 7 if the file type is not allowed?
AThe file is accepted and processed
BThe file is rejected with HTTP 400 error
CThe file size is checked next
DThe file contents are read
💡 Hint
Check row with Step 7 in execution_table for action on invalid file type
At which step does the code check if the file size is within the allowed limit?
AStep 2
BStep 11
CStep 12
DStep 4
💡 Hint
Look for size check condition in execution_table rows 4 and 12
If the file size is 2MB, what will be the result according to the execution flow?
AFile rejected due to size too large
BFile rejected due to invalid type
CFile accepted and filename returned
DFile size check skipped
💡 Hint
Refer to execution_table step 12 where size check fails and file is rejected
Concept Snapshot
FastAPI file validation:
- Use UploadFile and File(...) in endpoint
- Check file.content_type for allowed types
- Read file bytes asynchronously with await
- Check size with len(contents) <= max bytes
- Raise HTTPException(400) if invalid
- Return info if valid
Full Transcript
This visual execution shows how FastAPI handles file validation by first receiving the file upload request. It checks the file type against allowed types like image/png or image/jpeg. If the type is invalid, it rejects immediately with an error. If valid, it reads the file contents asynchronously. Then it checks the file size to ensure it is within the allowed limit (1MB in this example). If the file is too large, it rejects with an error. Otherwise, it accepts the file and returns its filename and size. Variables like file.content_type and contents change during execution. Key moments include why type is checked before reading contents, and why await is used for reading. The quiz questions help reinforce understanding of the flow and checks.

Practice

(1/5)
1. What is the main purpose of validating file size and type in a FastAPI upload endpoint?
easy
A. To ensure only allowed file types and sizes are accepted for security and performance
B. To automatically convert files to a specific format
C. To speed up the file upload process by skipping checks
D. To store files directly in the database without validation

Solution

  1. Step 1: Understand file validation purpose

    File validation ensures that only files meeting size and type rules are accepted.
  2. Step 2: Recognize security and performance reasons

    Validating prevents harmful files and avoids server overload from large files.
  3. Final Answer:

    To ensure only allowed file types and sizes are accepted for security and performance -> Option A
  4. Quick Check:

    File validation = security and performance [OK]
Hint: File validation protects server and users from bad files [OK]
Common Mistakes:
  • Thinking validation changes file content
  • Assuming validation speeds upload without checks
  • Ignoring security risks of unvalidated files
2. Which of the following is the correct way to declare a file upload parameter in a FastAPI endpoint to accept files asynchronously?
easy
A. def upload(file: UploadFile = File(...)):
B. def upload(file: str):
C. def upload(file: bytes):
D. def upload(file: int):

Solution

  1. Step 1: Identify FastAPI file upload type

    FastAPI uses UploadFile with File(...) to handle async file uploads.
  2. Step 2: Check parameter types

    Only UploadFile supports async file handling, bytes or str do not.
  3. Final Answer:

    def upload(file: UploadFile = File(...)): -> Option A
  4. Quick Check:

    UploadFile + File(...) = async file upload [OK]
Hint: Use UploadFile with File(...) for async uploads [OK]
Common Mistakes:
  • Using bytes or str instead of UploadFile
  • Missing File(...) dependency
  • Using int type for file parameter
3. Given this FastAPI code snippet, what will happen if a user uploads a 5MB PNG file?
from fastapi import FastAPI, File, UploadFile, HTTPException

app = FastAPI()

@app.post('/upload')
async def upload(file: UploadFile = File(...)):
    if file.content_type not in ['image/png', 'image/jpeg']:
        raise HTTPException(status_code=400, detail='Invalid file type')
    contents = await file.read()
    if len(contents) > 2_000_000:
        raise HTTPException(status_code=400, detail='File too large')
    return {'filename': file.filename, 'size': len(contents)}
medium
A. Returns filename and size successfully
B. Raises HTTPException with 'File too large'
C. Raises HTTPException with 'Invalid file type'
D. Raises a syntax error

Solution

  1. Step 1: Check file type condition

    The file is PNG, which is allowed, so no error here.
  2. Step 2: Check file size condition

    The file size is 5MB (5,000,000 bytes), exceeding 2,000,000 limit, so it raises 'File too large'.
  3. Final Answer:

    Raises HTTPException with 'File too large' -> Option B
  4. Quick Check:

    File size > 2MB = 'File too large' error [OK]
Hint: Check size limit after reading file contents [OK]
Common Mistakes:
  • Confusing file type error with size error
  • Not reading file contents before size check
  • Assuming no error for large files
4. Identify the error in this FastAPI file validation code:
from fastapi import FastAPI, File, UploadFile, HTTPException

app = FastAPI()

@app.post('/upload')
async def upload(file: UploadFile = File(...)):
    if file.content_type != 'image/png' or file.content_type != 'image/jpeg':
        raise HTTPException(status_code=400, detail='Invalid file type')
    contents = await file.read()
    if len(contents) > 1_000_000:
        raise HTTPException(status_code=400, detail='File too large')
    return {'filename': file.filename}
medium
A. The file size check uses wrong comparison operator
B. UploadFile should not be used with File(...)
C. The file type condition always raises error due to incorrect logic
D. Missing await keyword before file.read()

Solution

  1. Step 1: Analyze file type condition logic

    The condition uses 'or' with != checks, so it is always true (a file can't be both types).
  2. Step 2: Understand consequence of condition

    This causes the error to always raise, rejecting all files incorrectly.
  3. Final Answer:

    The file type condition always raises error due to incorrect logic -> Option C
  4. Quick Check:

    Incorrect 'or' with != always true = logic error [OK]
Hint: Use 'and' when checking multiple 'not equals' conditions [OK]
Common Mistakes:
  • Using 'or' instead of 'and' in file type checks
  • Forgetting to await file.read()
  • Misunderstanding UploadFile usage
5. You want to create a FastAPI endpoint that accepts only PDF files smaller than 3MB. Which code snippet correctly implements this validation?
hard
A. async def upload(file: UploadFile = File(...)): contents = await file.read() if file.content_type == 'application/pdf' or len(contents) < 3_000_000: return {'filename': file.filename} raise HTTPException(400, 'Invalid file')
B. async def upload(file: UploadFile = File(...)): if file.content_type == 'application/pdf' or len(await file.read()) < 3_000_000: return {'filename': file.filename} raise HTTPException(400, 'Invalid file')
C. async def upload(file: UploadFile = File(...)): if file.content_type == 'application/pdf' or len(await file.read()) > 3_000_000: raise HTTPException(400, 'Invalid file') return {'filename': file.filename}
D. async def upload(file: UploadFile = File(...)): if file.content_type != 'application/pdf': raise HTTPException(400, 'Invalid type') contents = await file.read() if len(contents) > 3_000_000: raise HTTPException(400, 'Too large') return {'filename': file.filename}

Solution

  1. Step 1: Check file type validation

    Correct snippet uses != 'application/pdf' to reject invalid types before reading contents. Distractors misuse operators like 'or' instead of 'and' or check type after reading.
  2. Step 2: Check file size validation

    After type approval, read contents once and raise if len > 3_000_000. Combined conditions fail due to incorrect logic.
  3. Final Answer:

    Separate type (!=) and size (> 3MB) checks -> Option D
  4. Quick Check:

    != type reject + read then > size reject [OK]
Hint: Check type and size separately with correct logic [OK]
Common Mistakes:
  • Using 'or' instead of 'and' in conditions
  • Reading file multiple times causing empty content
  • Incorrect comparison operators in conditions