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

如何用Python Imaging Library(PIL)在FastAPI中保存上传的压缩图片?

问题分析

你的代码仅将压缩后的图片写入了内存中的BytesIO对象,但没有执行持久化操作——既没把内存里的图片数据写入本地文件系统,也没存入数据库,所以看起来图片完全没保存。另外,im.save()方法返回的是None,你不需要把它赋值回im,这会直接覆盖原本的Image对象,属于无效操作。

修复方案

方案1:保存到本地文件系统

如果要把压缩后的图片存到服务器本地,需要将BytesIO中的数据写入实际文件:

from PIL import Image
from io import BytesIO
import os

@app.post("/post_ads")
async def create_upload_files(title: str = Form(), body: str = Form(), 
    db: Session = Depends(get_db), files: list[UploadFile] = File(description="Multiple files as UploadFile")):
    # 确保保存目录存在
    save_dir = "./compressed_images"
    os.makedirs(save_dir, exist_ok=True)
    
    for file in files:
        im = Image.open(file.file)
        im = im.convert("RGB")
        im_io = BytesIO()
        # 直接调用save,不要赋值回im
        im.save(im_io, 'JPEG', quality=50)
        # 将文件指针移到开头,准备读取数据
        im_io.seek(0)
        
        # 生成保存文件名(替换原后缀为jpg)
        save_filename = f"{os.path.splitext(file.filename)[0]}.jpg"
        save_path = os.path.join(save_dir, save_filename)
        
        # 写入本地文件
        with open(save_path, "wb") as f:
            f.write(im_io.getvalue())
            
        # 可选:将文件路径存入数据库
        # new_ad = Ads(title=title, body=body, image_path=save_path)
        # db.add(new_ad)
        # db.commit()

方案2:直接存入数据库(二进制数据)

如果要把压缩后的图片以二进制形式存入数据库(对应字段类型为BLOB/BYTEA),可以直接获取BytesIO的二进制内容:

@app.post("/post_ads")
async def create_upload_files(title: str = Form(), body: str = Form(), 
    db: Session = Depends(get_db), files: list[UploadFile] = File(description="Multiple files as UploadFile")):
    
    for file in files:
        im = Image.open(file.file)
        im = im.convert("RGB")
        im_io = BytesIO()
        im.save(im_io, 'JPEG', quality=50)
        im_io.seek(0)
        # 获取压缩后的二进制数据
        image_binary = im_io.getvalue()
        
        # 将二进制数据存入数据库(假设Ads模型有image_binary字段)
        new_ad = Ads(title=title, body=body, image_binary=image_binary)
        db.add(new_ad)
        db.commit()
        db.refresh(new_ad)
额外注意事项
  • 处理完BytesIO后可以调用im_io.close()释放资源,或者用上下文管理器包裹操作。
  • 如果需要将压缩后的图片返回给前端,可以用FastAPI的StreamingResponse包装BytesIO对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 12:05:20