pillow 压缩必须在保存前完成,通过 bytesio 和 contentfile 处理并重设 name;按 mime 类型和 alpha 通道动态选 jpg/png;缩放+格式+quality=85 协同优化;注意 seek(0)、模式转换、扩展名与 content_type 同步。

上传时用 Pillow 压缩图片,别等存完再处理
压缩必须发生在保存到磁盘或数据库之前,否则你得读取、解码、重编码、再覆盖——多一次 I/O,还可能破坏原图元数据。Django 的 ImageField 本身不提供压缩逻辑,得在模型保存前或表单验证后手动干预。
常见错误是把压缩写在视图里“处理完再 save()”,结果忘了清空原始 file 对象的缓冲区,导致压缩后的图片尺寸没变(实际是旧文件被重新写入)。
- 在模型的
save()方法中操作self.image.file,但要先检查self.image and not self.image._committed - 用
BytesIO接收压缩后的二进制流,再用ContentFile包装,赋给self.image - 务必调用
self.image.seek(0)再读取,否则Pillow可能读到空内容 - 压缩后记得重设
self.image.name,否则文件扩展名可能错(比如上传.png却存成.jpg)
ImageField 存 JPG 还是 PNG?看场景别硬统一
JPG 压缩率高、体积小,适合照片类;PNG 支持透明通道和无损压缩,适合 Logo、图标、带文字的截图。硬把所有图转 JPG 会丢透明度,转 PNG 又会让照片体积翻倍。
更稳妥的做法是按 MIME 类型动态决定:image/jpeg → 保持 JPG 并压缩;image/png → 检查是否含 alpha,有就保留 PNG,没有就转 JPG 省空间。
- 用
self.image.file.content_type或Image.open(self.image).mode判断通道类型 -
convert('RGB')会删 alpha,convert('RGBA')在 JPG 上会报错,得先判断 - 保存时指定
format='JPEG'或format='PNG',别依赖文件扩展名 - Django 默认用文件扩展名推断
content_type,上传时若改了格式,记得同步更新self.image.file.content_type
压缩参数怎么设?quality=85 是甜点,不是标准
quality 参数不是线性指标:从 95→85 视觉几乎无损,体积降 30%;再降到 70 就可能出现色块;低于 60 基本不可用。别盲目设成 50 或写死 quality=75。
真正影响最终体积的是三件事:尺寸缩放 + 格式选择 + quality。光调 quality 不缩放,大图照样卡页面。
- 先用
thumbnail((1200, 800), Image.LANCZOS)缩放到合理展示尺寸(别用resize,它不保持宽高比) - JPG 用
quality=85,progressive=True(渐进式加载) - PNG 优先用
optimize=True+compress_level=6,别碰quality(PIL 不支持) - WebP 格式体积更小,但注意老版 Safari 不支持,用前先检查
request.META.get('HTTP_ACCEPT', '')
为什么压缩后图片变黑/花屏/404?三个易漏点
这类问题基本不是 Pillow 本身 bug,而是上下文没清理干净。最常踩的坑是:内存流没重置、文件指针漂移、MIME 和扩展名不一致。
-
BytesIO写完后没seek(0),后续ContentFile读到空字节 → 上传空文件 → 404 - 用
Image.open()打开self.image后没convert()就直接save()→ 某些 CMYK 或 P 模式图保存失败 → 花屏或黑图 - 改了图片格式但没改
self.image.name,比如 PNG 转 JPG 后还叫xxx.png→ Django 用扩展名生成 URL,Nginx 找不到对应文件 → 404 - DEBUG=False 时静态文件没配好,压缩后路径生成错,但错误日志里只报 404,容易误判为压缩逻辑问题
复杂点在于:同一张图在本地开发跑得通,上线后出问题——往往是因为生产环境 PIL 缺少 libjpeg 或 libwebp 支持,Image.SAVE 里压根没有对应 encoder。上线前一定用 python -c "from PIL import features; print(features.check('jpeg'))" 验证。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











