You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过FastAPI接收模板上传图像并调用AI模型完成预测?

问题原因分析
  • 第一个FileNotFoundError错误:你使用Form接收文件上传字段,拿到的只是上传文件的文件名字节串,并非图片实际内容,load_img将这个文件名当作本地磁盘路径读取,自然找不到对应文件。
  • 第二个422 Unprocessable Entity错误:两个原因共同导致:
    1. HTML上传表单没有添加enctype="multipart/form-data"属性,这是文件上传类表单的必填属性,否则浏览器只会传递文件名而非文件内容,请求格式不符合FastAPI的参数校验要求
    2. 后端接收文件类型参数需要用File注解,而非Form注解
修复方案

1. 修改HTML表单代码

给form标签添加enctype属性,修改后代码如下:

<form action="/prediction_page" method="post" enctype="multipart/form-data">
    <label for="image-upload" class="custom-file-upload">Select Image:</label>
    <input type="file" id="image-upload" name="dogcat_img" accept=".jpg,.png"><br>
    <input class="custom-submit-button" type="submit">
</form>

额外添加了accept属性限制可选文件类型,避免用户上传不符合要求的格式。

2. 修改FastAPI后端代码

修改后的完整代码如下:

from starlette.responses import RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi import FastAPI, File, UploadFile
from tensorflow.keras import preprocessing
from keras.models import load_model
import numpy as np
import uvicorn
import io

app = FastAPI()
app.mount("/Templates", StaticFiles(directory="Templates"), name="Templates")

# 路径前加r转为原始字符串,避免Windows下反斜杠转义问题
model_dir = r'F:\Saved-Models\Dog-Cat-Models\First_Generation_dog_cat_optuna.h5'
model = load_model(model_dir)

# 类别映射,方便返回可读结果
CLASS_MAPPING = {0: "猫", 1: "狗"}

@app.get('/')
async def index():
    return RedirectResponse(url="/Templates/index.html")

@app.post('/prediction_page')
async def prediction_form(dogcat_img: UploadFile = File(...)):
    # 读取上传的图片内容
    img_content = await dogcat_img.read()
    # 转为字节流对象供load_img读取
    img_byte_stream = io.BytesIO(img_content)
    pp_dogcat_image = preprocessing.image.load_img(img_byte_stream, target_size=(150, 150))
    pp_dogcat_image_arr = preprocessing.image.img_to_array(pp_dogcat_image)
    input_arr = np.array([pp_dogcat_image_arr])
    prediction = np.argmax(model.predict(input_arr), axis=-1)[0]
    # 返回可读结果,你也可以根据需求调整返回格式
    return {"预测结果": CLASS_MAPPING.get(prediction, "未知类别")}

if __name__ == '__main__':
    uvicorn.run(app, host='localhost', port=8000)

额外注意事项

  • 如果你不需要保存上传的文件,直接用bytes = File(...)接收参数也可以,不需要处理UploadFile的异步读取逻辑,代码更简洁:
    @app.post('/prediction_page')
    async def prediction_form(dogcat_img: bytes = File(...)):
        img_byte_stream = io.BytesIO(dogcat_img)
        # 后续处理逻辑和上面一致
    
  • 模型加载可以放到启动事件里处理,避免服务运行过程中模型意外被释放,也更符合FastAPI的最佳实践。

内容的提问来源于stack exchange,提问作者Luleo_Primoc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 00:45:04