如何用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
相关产品推荐
相关产品推荐

