I am trying to build a web app that will allow users to upload two files (a tiff image and an Excel file called the mapping file). So far, I have the following app.py and dynamic.html files:
from fastapi import FastAPI, UploadFile, File, Request
from fastapi.templating import Jinja2Templates
import base64
import io
import pandas as pd
from PIL import Image, ImageOps
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.get("/")
def dynamic_file(request: Request):
return templates.TemplateResponse("dynamic.html", {"request": request})
@app.post("/dynamic")
def dynamic(request: Request, image_file: UploadFile = File(...), mapping_file: UploadFile = File(...)):
# Read the image file contents
image_contents = image_file.file.read()
image_file.file.close()
# if image type is tiff
if image_file.content_type == "image/tiff":
# Convert TIFF image to PNG
image = Image.open(io.BytesIO(image_contents))
image_bytes = io.BytesIO()
image.save(image_bytes, format="PNG")
encoded_image = base64.b64encode(image_bytes.getvalue()).decode("utf-8")
else:
# Encode other image formats directly
image = Image.open(io.BytesIO(image_contents))
# Resize the image to half the size of the screen
width, height = image.size
new_size = (width // 2, height // 2)
resized_image = ImageOps.fit(image, new_size)
# Encode the resized image as a base64 string
image_bytes = io.BytesIO()
resized_image.save(image_bytes, format="PNG")
encoded_image = base64.b64encode(image_bytes.getvalue()).decode("utf-8")
# Read the mapping file contents
mapping_contents = mapping_file.file.read()
mapping_file.file.close()
# Read the mapping file as a Pandas DataFrame
mapping_df = pd.read_excel(io.BytesIO(mapping_contents))
return templates.TemplateResponse(
"dynamic.html", {"request": request, "img": encoded_image, "mapping": mapping_df})
<html>
<head>
<title>Rendering Dynamic Images Using FastAPI</title>
</head>
<body>
<form action="/dynamic" enctype="multipart/form-data" method="POST">
<input name="file" type="file" />
<input type="submit" />
</form>
{% if img %}
<h1>Rendered Image</h1>
<img src="data:image/jpeg;base64,{{ img }}" />
{% else %}
<h1>Image will be render here...</h1>
{% endif %}
</body>
</html>
My webapp used to work fine by displaying a button to upload the image file until I added the following second attempt of importing a file.
# Read the mapping file contents
mapping_contents = mapping_file.file.read()
mapping_file.file.close()
# Read the mapping file as a Pandas DataFrame
mapping_df = pd.read_excel(io.BytesIO(mapping_contents))
When I do that I get the following error message on the localhost control panel:
POST http://127.0.0.1:8000/dynamic 422 (Unprocessable Entity)
{"detail":[{"loc":["body","image_file"],"msg":"field required","type":"value_error.missing"},{"loc":["body","mapping_file"],"msg":"field required","type":"value_error.missing"}]}
How can I change my code to have this second import button functionality?