Files
im_webapp/docs/superpowers/specs/2026-09-29-web-clipboard-image-compatibility-design.md
T

2.7 KiB

Web 聊天图片粘贴兼容设计

日期:2026-09-29。范围仅限 web/ 新版聊天输入框的图片粘贴;不改旧版、后端、图片选择器或部署配置。

现状与目标

当前输入框只读取 clipboardData.items 中 kind=file 且 item.type 为 image/* 的首个项目。Windows 微信截图在不同浏览器中的剪贴板暴露形式尚无现场记录,因此不能断言根因;但 files、文件本身 MIME、内嵌 HTML 图片和浏览器 Clipboard API 均是当前实现未覆盖的可读路径。线上已经部署了现有粘贴功能。此前“多图暂存并配文字发送”按用户反馈撤回,本次保持识别到首张图片后立即发送,不加入预览、多图或图文合并。

方案

把图片提取逻辑放入一个可独立测试的小模块,输入为粘贴事件中的 DataTransfer,输出为首个可发送的 File 或“未取得图片”。按顺序尝试:

  1. 同步检查 items:对 kind=file 调用 getAsFile(),以所得文件的 MIME 为准,item.type 仅作补充;然后检查 files,避免浏览器只填充其中一个集合。
  2. 同步检查 text/html 中的 <img src="data:image/...">;只解码本地内嵌图片,不请求远程 URL,不执行 HTML。纯文字和普通 HTML 粘贴保持浏览器原生行为。
  3. 对没有可用同步图片、也没有纯文字,且事件带图片/文件线索或完全没有数据类型的情况,尝试 navigator.clipboard.read() 读取浏览器提供的 image/* Blob。仅含普通 HTML 的事件不走此兜底。此路径可能受权限或浏览器支持限制;网页无法越过浏览器直接读取 Windows 原生 CF_DIB 等格式。

只有确定要接管图片粘贴或进入无文字的异步兜底时,才在事件回调内同步 preventDefault()。不得在 await 之后访问原粘贴事件的数据。提取成功后仍调用现有 sendImage;提取或读取失败时对明确的图片粘贴给出简短提示,发送失败继续沿用现有错误提示。不得让纯文字粘贴触发发送或权限请求。

验收与测试

先写失败测试,再改实现。覆盖:items 的 PNG/JPEG/BMP、item.type 缺失但文件 MIME 正确、仅 files、getAsFile() 为空时回退、HTML 内嵌图片、Clipboard API 返回图片、权限拒绝、纯文字原生粘贴、远程 HTML 图片不抓取、多个图片只取首张。运行定向测试、前端构建和 lint;再用真实浏览器派发图片及文字粘贴事件,核对是否接管和既有即时发送路径。若无 Windows/微信运行环境,最终明确说明这一端到端组合尚未实测,不宣称已覆盖所有微信版本。

本次只做本地代码与验证;不推送、不部署。