navigator.clipboard复制文字和图片的问题

最近要实现一个"将图片和文字复制到剪切板"的功能。接下来是我的实现的过程,在这个过程中踩到一些坑,记录一下。

将文字复制到剪切板

将一段文字复制到剪切板是很容易的一件事,W3C给我们提供了一些API。

  1. navigator.clipboard.writeText()     可以直接使用navigator.clipboard.writeText()来将一段文字复制到剪切板。
ts 复制代码
const copyText = (
    text: string,
): Promise<string> => {
    return new Promise((resolve, reject) => {
        // 剪切板API
        const clipBoardApi = navigator.clipboard;
        if (clipBoardApi) {
            clipBoardApi.writeText(text)
            .then(() => resolve('复制成功'))
            .catch(reject);
        } else {
            reject('浏览器不支持navigator.clipboard方法');
        }
    });
}
  1. navigator.clipboard.write()     对于navigator.clipboard.writeText()来说,看到writeText就知道这个API明显只能够复制文字,和我们要实现的功能不太相符,所以我就使用了navigator.clipboard.write()方法。
ts 复制代码
const copyText = (
    text: string,
): Promise<string> => {
    return new Promise((resolve, reject) => {
        // 剪切板API
        const clipBoardApi = navigator.clipboard;
        if (clipBoardApi) {
            const clipboardItemText = new Blob([text], {type: 'text/plain'});
            const clipboardItem = new ClipboardItem({
                'text/plain': clipboardItemText,
            })
            clipBoardApi.write([clipboardItem])
            .then(() => resolve('复制成功'))
            .catch(reject);
        } else {
            reject('浏览器不支持navigator.clipboard方法');
        }
    })
}

将图片复制到剪切板

更具上述使用navigator.clipboard.write()方法将文字复制到剪切板后,我们将代码改造一下就可以将图片复制到剪切板。

ts 复制代码
const copyImage = (
    url: string,
): Promise<string> => {
    return new Promise(async (resolve, reject) => {
        // 剪切板API
        const clipBoardApi = navigator.clipboard;
        if (clipBoardApi) {
            const image = await fetch(url).then((response) => response.blob());
            const clipboardItemImage = new Blob([image], {type: 'image/png'});
            const clipboardItem = new ClipboardItem({
                'image/png': clipboardItemImage,
            })
            clipBoardApi.write([clipboardItem])
            .then(() => resolve('复制成功'))
            .catch(reject);
        } else {
            reject('浏览器不支持navigator.clipboard方法');
        }
    })
}

将文字和图片复制

复制文字和图片到剪切板的代码都实现了,那么我们应该怎么样将其整合起来,将文字和图片一同复制到剪切板呢?看到ClipboardItem事例的参数是要求传递一个对象的时候,就大致有了思路,我们将文字和图片一起传入试一试。

ts 复制代码
const copyImageText = (
  url: string,
  text: string,
): Promise<string> => {
  return new Promise(async (resolve, reject) => {
      // 剪切板API
      const clipBoardApi = navigator.clipboard;
      if (clipBoardApi) {
          // 图片
          const image = await fetch(url).then((response) => response.blob());
          const clipboardItemImage = new Blob([image], {type: 'image/png'});
          // 文字
          const clipboardItemText = new Blob([text], {type: 'text/plain'});
          const clipboardItem = new ClipboardItem({
              'image/png': clipboardItemImage,
              'text/plain': clipboardItemText,
          })
          clipBoardApi.write([clipboardItem])
          .then(() => resolve('复制成功'))
          .catch(reject);
      } else {
          reject('浏览器不支持navigator.clipboard方法');
      }
  })
}

但是上述代码测试下来发现只复制了文字,并没有复制图片。那么我们可以换种思路,navigator.clipboard.write()方法的参数传递是一个数组。

ts 复制代码
const copyImageText2 = (
    url: string,
    text: string,
): Promise<string> => {
    return new Promise(async (resolve, reject) => {
        // 剪切板API
        const clipBoardApi = navigator.clipboard;
        if (clipBoardApi) {
            // 图片
            const image = await fetch(url).then((response) => response.blob());
            const clipboardItemImage = new Blob([image], {type: 'image/png'});
            // 文字
            const clipboardItemText = new Blob([text], {type: 'text/plain'});
            const handleClipboardItem = (key: string, value: Blob) => new ClipboardItem({
                [key]: value,
            })
            clipBoardApi.write([
                handleClipboardItem('image/png', clipboardItemImage),
                handleClipboardItem('text/plain', clipboardItemText),
            ])
            .then(() => resolve('复制成功'))
            .catch(reject);
        } else {
            reject('浏览器不支持navigator.clipboard方法');
        }
    })
}

经过测试下来,发现报错了。

Uncaught (in promise) DOMException: Support for multiple ClipboardItems is not implemented.

查询文档中...

查找了相关的文档后,我发现无法在单次操作中同时复制多种类型的数据(例如文本和图片)到剪贴板。

最后实现方案

最后的实现方案就是将文字和图片都转成文字复制到剪切板,例如:123<img src=""/>,然后复制到编译器后在编译器里进行处理,将<img src="" />转换成对应的图片,因为处理的过程是基于ckEditor编译器的,过于复杂,所以具体过程就不放出来了。

总结

以上的代码和总结仅是本人的灼见,希望各位大佬们多批评。

相关推荐
wordbaby12 小时前
Expo 进阶指南:赋予 TanStack Query “原生感知力” —— 深度解析 AppState 与 NetInfo
前端·react native
Moment12 小时前
从美团全栈化看 AI 冲击:前端转全栈,是自救还是必然 🤔🤔🤔
前端·后端·面试
天问一12 小时前
使用 Vue Router 进行路由定制和调用的示例
前端·javascript·vue.js
韩立学长14 小时前
【开题答辩实录分享】以《基于Vue的非遗文化知识分享平台的设计与实现》为例进行选题答辩实录分享
前端·javascript·vue.js
优弧14 小时前
离开舒适区100天,我后悔了吗?
前端·后端·面试
胡gh14 小时前
css的臂膀,前端动效的利器,还是布局的“隐形陷阱”?
前端·css·html
灵感菇_14 小时前
Flutter Riverpod 完整教程:从入门到实战
前端·flutter·ui·状态管理
用户214118326360214 小时前
紧急修复!Dify CVE-2025-55182 高危漏洞,手把手教你升级避坑
前端
前端 贾公子14 小时前
Vue响应式原理学习:基本原理
javascript·vue.js·学习
飛67915 小时前
从 0 到 1 掌握 Flutter 状态管理:Provider 实战与原理剖析
开发语言·javascript·ecmascript