2.7 KiB
Web 聊天图片粘贴兼容设计
日期:2026-09-29。范围仅限 web/ 新版聊天输入框的图片粘贴;不改旧版、后端、图片选择器或部署配置。
现状与目标
当前输入框只读取 clipboardData.items 中 kind=file 且 item.type 为 image/* 的首个项目。Windows 微信截图在不同浏览器中的剪贴板暴露形式尚无现场记录,因此不能断言根因;但 files、文件本身 MIME、内嵌 HTML 图片和浏览器 Clipboard API 均是当前实现未覆盖的可读路径。线上已经部署了现有粘贴功能。此前“多图暂存并配文字发送”按用户反馈撤回,本次保持识别到首张图片后立即发送,不加入预览、多图或图文合并。
方案
把图片提取逻辑放入一个可独立测试的小模块,输入为粘贴事件中的 DataTransfer,输出为首个可发送的 File 或“未取得图片”。按顺序尝试:
- 同步检查
items:对kind=file调用getAsFile(),以所得文件的 MIME 为准,item.type仅作补充;然后检查files,避免浏览器只填充其中一个集合。 - 同步检查
text/html中的<img src="data:image/...">;只解码本地内嵌图片,不请求远程 URL,不执行 HTML。纯文字和普通 HTML 粘贴保持浏览器原生行为。 - 对没有可用同步图片、也没有纯文字,且事件带图片/文件线索或完全没有数据类型的情况,尝试
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/微信运行环境,最终明确说明这一端到端组合尚未实测,不宣称已覆盖所有微信版本。
本次只做本地代码与验证;不推送、不部署。