如何使用FastAPI和Jinja2在HTML页面中显示上传的图片?
问题:FastAPI + Jinja2 上传图片后无法通过img标签显示
我用FastAPI和Jinja2搭建了一个图片上传页面,上传完成后通过图片名称链接打开另一个页面展示图片。目前上传和链接功能正常,但img标签无法显示图片,求解决办法。
现有代码
main.py
from fastapi import FastAPI, File, UploadFile, Request from fastapi.responses import HTMLResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates app = FastAPI() app.mount("/static", StaticFiles(directory="static"), name="static") """ upload file and save it to local """ @app.post("/upload-file") async def upload_file(file: UploadFile = File(...)): with open(file.filename, "wb") as f: f.write(file.file.read()) return {"filename": file.filename} ''' create html page to show uploaded file ''' @app.get("/") async def root(): html_content = """ <html> <head> <title>Upload File</title> </head> <body> <h1>Upload File</h1> <form action="/upload-file/" method="post" enctype="multipart/form-data"> <input type="file" name="file" /> <input type="submit" /> </form> </body> </html> """ return HTMLResponse(content=html_content) templates = Jinja2Templates(directory="templates") @app.get("/{filename}", response_class=HTMLResponse) async def read_item(request: Request, filename: str): return templates.TemplateResponse("template.html", {"request": request,"filename": filename})
template.html
<!DOCTYPE html> <html> <head> <title>HTML img Tag</title> </head> <body> <img src= "{{./filename}} " alt="uploaded image" width="400" height="400"> </body> </html>
我也接受更优、更简便的实现方式,谢谢。
解决办法
问题根源
- 文件存储路径错误:上传的图片直接存在项目根目录,但FastAPI仅配置
/static路径对应本地static目录的静态文件,根目录文件无法被静态服务访问。 - img标签语法错误:Jinja2模板中
{{./filename}}的写法不符合语法,无法生成正确的静态文件URL。
修改步骤
1. 修正文件存储路径
修改/upload-file接口,将文件保存到static目录下(若static目录不存在需手动创建):
@app.post("/upload-file") async def upload_file(file: UploadFile = File(...)): # 拼接static目录的文件路径 file_path = f"static/{file.filename}" with open(file_path, "wb") as f: f.write(file.file.read()) return {"filename": file.filename}
2. 修正模板的img标签路径
在template.html中使用FastAPI提供的url_for函数生成正确的静态文件URL:
<!DOCTYPE html> <html> <head> <title>HTML img Tag</title> </head> <body> <img src="{{ url_for('static', path=filename) }}" alt="uploaded image" width="400" height="400"> </body> </html>
优化建议(可选)
- 处理文件重名:给上传文件添加随机前缀或时间戳,避免同名文件被覆盖:
import uuid from pathlib import Path @app.post("/upload-file") async def upload_file(file: UploadFile = File(...)): # 生成唯一文件名 unique_filename = f"{uuid.uuid4().hex}_{file.filename}" file_path = Path("static") / unique_filename with open(file_path, "wb") as f: f.write(file.file.read()) return {"filename": unique_filename} - 上传页面改用模板:将首页HTML内容移至
templates目录下的upload.html,用TemplateResponse返回,更贴合Jinja2使用习惯:@app.get("/", response_class=HTMLResponse) async def root(request: Request): return templates.TemplateResponse("upload.html", {"request": request})upload.html内容:<html> <head> <title>Upload File</title> </head> <body> <h1>Upload File</h1> <form action="/upload-file/" method="post" enctype="multipart/form-data"> <input type="file" name="file" /> <input type="submit" /> </form> </body> </html>
内容的提问来源于stack exchange,提问作者Aboude
相关产品推荐
相关产品推荐

