用户从 iPhone 上传的原图是 HEIC,接口返回 400,原文 unsupported image format,安卓用户上传 jpg 全部正常,服务端只是把文件字节直接 base64 后发出去。

一开始怀疑是「前端按扩展名判断类型,没有真正转码」,查了一圈,方向不对。

把日志和配置对完,能解释这个现象的基本就这几处。接口只接受 png、jpeg、webp、gif 这几种格式。少数情况下是HEIC 的文件头被识别成 application/octet-stream。

还有一种情况,部分浏览器预览时已转码,服务端拿到的又是原图。

动手时先读文件头确认真实格式

python -c "b=open('IMG_0001.HEIC','rb').read(12);print(b[:12])"

再往下用 pillow-heif 转成 jpeg 再上传

python -c "from PIL import Image;import pillow_heif;pillow_heif.register_heif_opener();Image.open('IMG_0001.HEIC').convert('RGB').save('out.jpg','JPEG',quality=90)"

接着在入口按魔数而不是扩展名分流

python -c "import imghdr;print(imghdr.what('IMG_0001.HEIC'))"

转码后重新调用接口验证

python call_api.py --file out.jpg --model gpt-4o-mini

排查用的命令都是临时敲的,没有写成脚本,事后才整理。

恢复的判定其实很直接。HEIC 上传后服务端自动转码,接口返回 200,识别结果与同场景的 jpg 一致。

移动端上传的格式比想象中杂,入口按文件头判断并统一转码,比在业务里逐个兼容省事。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189