多模态Agent上传图片:前端压缩格式与预览实战

接了个图片问答的需求:用户传张图,AI 看图回答。听着就是个 <input type=file>,真做下去才知道前端要替用户兜多少事------几十兆的原图直接传,请求超时;HEIC 格式后端不认;预览图把内存吃爆。一篇实战,把上传这条链路的脏活拆开讲。

先压,别让用户传原图

现在手机随手一拍就是十几兆,原图传上去既慢又烧带宽,多模态模型其实也不需要那么高分辨率。前端用 canvas 等比缩到长边 1568px 左右(多数视觉模型的友好尺寸)再传,体积能砍九成:

ini 复制代码
async function compress(file: File, maxEdge = 1568, quality = 0.82): Promise<Blob> {
  const bitmap = await createImageBitmap(file);
  const scale = Math.min(1, maxEdge / Math.max(bitmap.width, bitmap.height));
  const w = Math.round(bitmap.width * scale);
  const h = Math.round(bitmap.height * scale);
  const canvas = new OffscreenCanvas(w, h);
  const ctx = canvas.getContext('2d')!;
  ctx.drawImage(bitmap, 0, 0, w, h);
  bitmap.close(); // 重要,及时释放,否则内存涨得吓人
  return canvas.convertToBlob({ type: 'image/jpeg', quality });
}

bitmap.close() 那行别漏。我做批量上传时没释放,连传十几张内存直接飙到几百兆,移动端 webview 当场崩。OffscreenCanvas 还能放进 Web Worker 压,不卡主线程,长列表上传体验好很多。

HEIC 是个大坑

iPhone 默认存 HEIC,浏览器 <img> 和 canvas 大多不认,createImageBitmap 直接抛错。我一开始没考虑,苹果用户上传全军覆没,测试机是安卓还没测出来,上线才暴雷。

处理方式:检测到 HEIC 先用 heic2any 之类转成 jpeg 再走压缩。代价是这个库 gzip 后小两百 KB,我做了动态 import,只有真遇到 HEIC 才加载,别让所有用户为少数格式买单:

javascript 复制代码
async function normalize(file: File): Promise<File> {
  if (/heic|heif/i.test(file.type) || /.heic$/i.test(file.name)) {
    const { default: heic2any } = await import('heic2any'); // 按需加载
    const blob = await heic2any({ blob: file, toType: 'image/jpeg' });
    return new File([blob as Blob], file.name.replace(/.heic$/i, '.jpg'), { type: 'image/jpeg' });
  }
  return file;
}

预览图用 objectURL,记得 revoke

预览别用 FileReader 读 base64------大图转 base64 又慢又占内存,还会把 DOM 撑大。用 URL.createObjectURL 几乎零成本,但必须配对 revoke,否则这块内存到页面关都不释放:

ini 复制代码
const url = URL.createObjectURL(file);
previewEl.src = url;
previewEl.onload = () => URL.revokeObjectURL(url); // 加载完立刻回收

删除某张待传图片时也要 revoke 对应的 url。我有个版本忘了在删除分支里回收,用户反复添加删除几十次后,内存只涨不跌,典型的泄漏。

上传前的体面校验

别等传到后端才报「格式不支持」。前端先把住门------类型白名单、单张大小上限、张数上限,错误就地提示,省一次往返也省用户的脾气:

kotlin 复制代码
function validate(file: File) {
  const ok = ['image/jpeg', 'image/png', 'image/webp', 'image/heic'];
  if (!ok.includes(file.type)) return '只支持 JPG/PNG/WebP/HEIC';
  if (file.size > 20 * 1024 * 1024) return '单张不能超过 20MB';
  return null;
}

一个没做完美的

压缩质量我固定在 0.82,对照片够用,但用户传的若是带细密文字的截图,压完字会糊,影响模型识别。理想做法是按内容自适应质量,我评估了下投入产出比,暂时没做,先在文案里提示「文字截图建议原图」绕过去。算个偷懒,但当下够用。

多模态那头的模型能力我直接接讯飞 这类 MaaS 的现成 API,不操心算力和模型怎么部署,前端只把图片处理这条链路打磨干净。

你们上传链路还有啥隐形坑?HEIC 之外我估计还有冷门格式,评论区补补刀。

相关推荐
私人珍藏库3 小时前
[Android] PeakFinder AR v4.8.89 (山峰全景识别+增强现实山峰查看器)
android·人工智能·智能手机·ar·工具·软件
CS创新实验室3 小时前
算法、齿轮与硅基大脑:数值计算发展简史
人工智能·算法·数值计算
能有时光3 小时前
PyTorch KernelAgent 源码解读 ---(4)--- ExtractorAgent
人工智能·pytorch·python
fthux4 小时前
GitZip Pro 源码解析:一个 GitHub 文件/文件夹下载扩展是如何工作的(一)整体架构与扩展入口
人工智能·ai·开源·github·open source
aqi004 小时前
15天学会AI应用开发(十七)使用LangGraph实现会话记忆功能
人工智能·python·大模型·ai编程·ai应用
xixixi777775 小时前
三大 AI 安全里程碑:Akamai 高危风险预警、智能体水印强制落地、PQC 量子安全全产业链统一
大数据·人工智能·安全·ai·大模型·智能体·政策
AI小码5 小时前
LLM 应用的缓存工程:当每次 API 调用都在燃烧成本
java·人工智能·spring·计算机·llm·编程·api
code 小楊5 小时前
AI函数调用:Function Calling从理论到实战全解析
人工智能
delishcomcn5 小时前
智切未来:AI算法如何重塑不干胶标签分切机的精度与效率边界
人工智能·神经网络·计算机视觉
观远数据5 小时前
ChatBI选型对比:从意图识别到SQL修复,六个维度打分决定是否值得投产
数据库·人工智能·sql