使用 navigator.clipboard.read() 读取富文本需在用户触发的 paste 事件中调用,经语义解析、白名单过滤与 DOM 重建实现流式脱敏,兼顾安全与可读性,并提供多层降级兼容策略。

直接用 navigator.clipboard.read() 读取富文本剪贴板内容后,不能原样插入页面——HTML 可能含恶意脚本、危险标签或失控样式。流式语义脱敏不是简单删标签,而是按语义层级逐层解析、过滤、重构,兼顾可读性与安全性。
明确读取时机与权限前提
必须在用户触发的事件中调用(如 paste 事件),且不能脱离同步上下文:
- 监听
document.addEventListener('paste', handler),并在 handler 内立即event.preventDefault()阻止默认粘贴行为 - 调用前可选预检权限:
const perm = await navigator.permissions.query({ name: 'clipboard-read' }),若为'denied'则跳过读取 - 确保页面运行在 HTTPS 或
localhost环境下,否则 API 不可用
分类型提取并识别语义结构
read() 返回 ClipboardItem[],需遍历每个 item 的 types,对关键类型做针对性处理:
-
优先尝试
text/html:它通常包含带内联图片(data:image/xxx;base64)的完整 HTML 片段,语义最丰富 -
降级 fallback
text/plain:无格式纯文本,适合提取基础语义(如段落、列表项文字),但丢失结构 -
单独图片(
image/*)不直接混入 HTML 流:它们是独立二进制项,应单独转为 blob URL 并按语义位置插入(例如“此处有一张图”占位后异步加载)
流式脱敏:解析 → 过滤 → 重建 DOM
拿到 text/html 字符串后,不使用 innerHTML 直接写入,而是走 DOM 解析流水线:
- 用
new DOMParser().parseFromString(html, 'text/html')构建临时文档片段 - 遍历所有节点,按语义白名单保留:
p、h1-h6、ul/ol/li、strong/em、br、img(仅允许src为 data URI 或已知安全域名) - 移除所有
script、iframe、on*属性、style属性(或仅保留极简内联样式如color、font-weight) - 对
img标签,提取src后校验是否为合法 data URI;若非 data URI,丢弃或替换为占位图标 - 最终用
document.importNode()安全导入清洗后的节点树,避免执行任何脚本
兼容与降级策略
并非所有环境都支持 read(),需有备选路径:
- 检测
navigator.clipboard?.read是否存在,不存在则监听paste事件中的event.clipboardData?.getData('text/html')(旧版 Safari/IE 兼容) - 若连
clipboardData都不可用,回退到纯文本提取:event.clipboardData?.getData('text/plain') - 整个流程包裹
try/catch,失败时提示用户“粘贴内容受限,已自动转为纯文本”并启用降级逻辑

















