JS - 获取剪切板内容 Clipboard API
目录
- 1,需求
- 最终效果
- 2,实现
- 示例
- 3,注意点
- 1,只支持安全上下文环境
- 2,只能读取当前页面的剪切板
- 3,权限获取问题
- 4,获取内容的 MIME_TYPE 问题
- 1,文本内容
- 2,图片内容
- 5,只能获取剪切板内容的 blob 类型
- 6,`URL.revokeObjectURL` 的时机
- 4,其他
- paste 事件简单举例
1,需求
一个问题咨询表单页,可以上传图片。因为有截图的场景,所以需要得先截图保存在本地再上传,比较繁琐。
想从剪切板获取截图后,直接上传。
最终效果
2,实现
从剪切板获取的内容分为文本和非文本,分别对应2个API,
- navigator.clipboard.readText()
- navigator.clipboard.read(),可以用它来获取图片。
获取的内容是 ClipboardItem 对象。
示例
完整代码:
<template><div ref="refPasteBox"></div><button @click="getClipImg">获取剪切板图片</button>
</template><script setup lang="ts">
import { ref } from "vue";const refPasteBox = ref<HTMLDivElement>();
const getClipImg = async () => {try {const clipboardContent = await navigator.clipboard.read();const clipboardItem = clipboardContent[0];let noImg = true;for (const type of clipboardItem.types) {if (type === "image/png") {noImg = false;const blob = await clipboardItem.getType(type);const url = URL.createObjectURL(blob);// 如果需要 File 对象const file = new File([blob], "clipboard-image.png", { type });console.log(file);const img = document.createElement("img");img.src = url;img.width = 300;img.onload = () => {URL.revokeObjectURL(img.src);};refPasteBox.value?.appendChild(img);}}if (noImg) {alert("当前剪切板中没有图片。\n Windows 系统可通过快捷键\n ⌘+V \n查看剪切板");}} catch (err: any) {if (err.name === "NotAllowedError") {console.log("用户拒绝了访问剪贴板");} else {console.error("无法读取剪贴板内容: ", err);}}
};
</script>
3,注意点
1,只支持安全上下文环境
安全上下文,可以简单理解为只支持 https
协议和本地 http://127.0.0.1
、http://localhost
。
在 http
环境下是 undefined
,
2,只能读取当前页面的剪切板
有5个区域:
- 页面内容显示区域
- 地址栏
- 书签栏
- 控制台
- 其他应用
在执行 await navigator.clipboard.read()
相关 API 时,必须聚焦到区域1,否则会有如下报错!
正常情况下通过按钮点击来执行 API 时,都是满足的。
如果想在控制台中简单测试,可以用计时器。在控制台执行后,迅速点击页面区域就可以正常执行。
setTimeout(async () => {const clipboardContent = await navigator.clipboard.read();console.log(clipboardContent);
}, 2000);
3,权限获取问题
当第一次请求剪切板【读权限】时,也就是执行 await navigator.clipboard.read()
时,会弹出确认弹窗:
允许后就可以正常使用了。如果禁止了,无法通过再次执行代码打开该弹窗!只能手动重置权限。
4,获取内容的 MIME_TYPE 问题
const getClipImg = async () => {try {const clipboardContent = await navigator.clipboard.read();const clipboardItem = clipboardContent[0];console.log(clipboardItem);for (const type of clipboardItem.types) {if (type === "image/png") {const blob = await clipboardItem.getType(type);}}} catch (err) {console.log(err)}
};
示例代码中,通过 for 循环获取了剪切板内容的 type
,它有几个特点:
1,文本内容
无论是从什么地方手动复制的文本,type
都是2个:text/plain
和 text/html
。
2,图片内容
1,如果是截图,type
统一为 image/png
。
2,如果是从网页上复制的图片(无论原图片是什么格式),type
统一都是2个:text/html
和 image/png
。
所以,只需要判断 MIME 类型为 image/png
即可获取对应的图片。
另外,从本地复制的文件(图片,excel等) 无法通过
await navigator.clipboard.read()
API 获取。
5,只能获取剪切板内容的 blob 类型
// ...
for (const type of clipboardItem.types) {if (type === "image/png") {const blob = await clipboardItem.getType(type);}
}
通过 getType 可以获取剪切板的内容,结果为 blob
类型,
如果需要预览,需要转换为 url
。
const url = URL.createObjectURL(blob);
如果需要 File 对象(比如上传),需要手动转换。
const file = new File([blob], "clipboard-image.png", { type });
6,URL.revokeObjectURL
的时机
if (type === "image/png") {const blob = await clipboardItem.getType(type);const url = URL.createObjectURL(blob);const img = document.createElement("img");img.src = url;img.width = 300;img.onload = () => {URL.revokeObjectURL(img.src);};document.body.appendChild(img);
}
当通过 URL.createObjectURL() 创建可用于预览的对象 url
后,不能通过 URL.revokeObjectURL
立即释放该对象,否则图片无法显示。需要等到图片加载完成才行,或者不释放问题也不大。
4,其他
剪切板 API 获取的内容,和 paste 事件得到的内容是有区别的。
paste
事件一般用于富文本编辑,粘贴各种类型的文件。
- 剪切板不能获取本地复制的文件,
paste
事件可以。 - MIME 类型问题,从网页复制的是
type/html
,但却可以获取File
对象。为了兼容,应该用event.clipboardData?.files[0]
并加判断,而不是items[0].getAsFile()
, getAsFile-参考。 - 获取的 DataTransfer 对象,虽然 MDN 上的解释是拖动获取的内容,但其实也是粘贴事件获取的内容。
paste 事件简单举例
注意,ClipboardEvent
对象中部分内容通过 console.log
是看不到输出的,类似打印 currentTarget 得到的是 null
,但是可以使用的。
<template><div ref="refClipBox" class="clip-box" @paste="getPasteImage" contenteditable="true"></div>
</template><script setup lang="ts">
import { ref } from "vue";const refClipBox = ref<HTMLDivElement>();
function getPasteImage(event: ClipboardEvent) {event.preventDefault();console.log(event);// 检查剪贴板项目const items = event.clipboardData?.items || [];if (items[0].type.indexOf("image") === 0 || items[0].type === "text/html") {// const blob = items[0].getAsFile();const blob = event.clipboardData?.files[0];const url = URL.createObjectURL(blob);const img = document.createElement("img");img.src = url;img.width = 300;img.onload = () => {URL.revokeObjectURL(img.src);};refClipBox.value?.appendChild(img);} else {console.log("不是图片");}
}
</script>
<style>
.clip-box {width: 300px;height: 300px;border: 1px solid #000;
}
</style>
以上。
参考
相关文章:

JS - 获取剪切板内容 Clipboard API
目录 1,需求最终效果 2,实现示例 3,注意点1,只支持安全上下文环境2,只能读取当前页面的剪切板3,权限获取问题4,获取内容的 MIME_TYPE 问题1,文本内容2,图片内容 5&#x…...
Qt自动打开文件夹并高亮文件
在Qt中,如果你想要打开一个文件夹并在文件管理器中高亮显示(选中)某个文件,你可以使用以下方法: 对于Windows系统,你可以使用QProcess来启动explorer命令,并带上/select,参数来高亮显示文件。以…...

神经网络-MNIST数据集训练
文章目录 一、MNIST数据集1.数据集概述2.数据集组成3.文件结构4.数据特点 二、代码实现1.数据加载与预处理2. 模型定义3. 训练和测试函数4.训练和测试结果 三、总结 一、MNIST数据集 MNIST数据集是深度学习和计算机视觉领域非常经典且基础的数据集,它包含了大量的手…...
数据结构二
求 sizeof(name1)?(晟安信息) struct name1{ char str; short x; int num; }; sizeof name1内存对齐 8个字节 char分配8个字节 然后 short节省空间在4个字节中 而这个int独自分配分配内存 4个字节所以共8个字节 (电工时代) typedef struct _a { char c1; long i…...
Python|基于Kimi大模型,删除已上传的“指定文档”或“全部文档”(6)
前言 本文是该专栏的第6篇,后面会持续分享AI大模型干货知识,记得关注。 在本专栏上一篇《Python|基于Kimi大模型,实现上传文档并进行对话(5)》中,笔者有详细介绍“基于kimi大模型,上传指定文档并结合prompt,获取目标文本数据”。对此感兴趣的同学,可以直接点击翻阅查…...

CenterPoint-KITTI:环境配置、模型训练、效果展示;KITTI 3D 目标检测数据集下载
目录 前言 Python虚拟环境创建以及使用 KITTI3D目标检测数据集 CenterPoint-KITTI编译遇到问题合集 ImportError: cannot import name VoxelGenerator from spconv.utils 失败案例 最终解决方案 对于可选参数,road plane的处理 E: Unable to locate packag…...
【Android】ViewPager
1.ViewPager的简介和作用 ViewPager是android扩展包v4包中的类,这个类可以让用户左右切换当前的view,用于允许用户在几个页面(或称为碎片)之间左右滑动切换。它通常用于创建像画廊或轮播图那样的用户体验。 ViewPager类直接继承了…...
[go] 命令模式
命令模式 将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。 模型说明 触发者类负责对请求进行初始化,其中必须包含一个成员变量来存储对于命令对象的引用。触发命令,而不同接受者直接…...
代码随想录冲冲冲 Day48 单调栈Part2
42. 接雨水 关键点有以下几个 首先是怎么去理解接雨水 其实就是找每一个段的左边第一个最大值和右边第一个最大值 既然是最大值 那么单调栈就是递增的 左边第一个最大值其实就是pop掉中间的之后st.top 由于是出现大于等于情况时候进行操作 所以右边最大值就是i 接下来就…...
企业内训|Nvidia智算中心深度技术研修-某智算厂商研发中心
课程概述 此企业内训课程“Nvidia智算中心的深度技术研修”专为某智算厂商研发中心设计,内容涵盖了从基础设施构建到高性能计算优化的全方位技术要点。课程为期七天,分模块详细讲解了NV算力资源的网络架构、存储优化、智算集群的建设与自动化管理、NCCL…...
《算法笔记》例题解析 第3章入门模拟--3图形输出(9题)2021-03-03
例题 旋转方阵 题目描述 Time Limit: 1000 ms Memory Limit: 256 mb 打印出一个旋转方阵,见样例输出。 输入描述: 输入一个整数n(1 < n < 20), n为方阵的行数。 输出描述: 输出一个大小为n*n的距阵 输入 5 输出 1 16 15 14 13 2 17 24 23 12 3 18 25 22 11 4 1…...

合宙Air201模组LuatOS:PWRKEY控制,一键解决解决关机难问题
不知不觉间,我们已经发布拉期课程:hello world初体验,点灯、远程控制、定位和扩展功能,你学的怎么样?很多伙伴表示已经有点上瘾啦!合宙Air201,如同我们一路升级打怪的得力法器,让开发…...
Kafka 命令详解及使用示例
文章目录 Kafka 命令详解及使用示例Kafka 命令详解kafka-topics.sh:主题管理创建主题创建带副本的主题修改主题分区数了解分区分布列出主题查看主题详情删除主题 kafka-console-producer.sh:消息生产者发送消息到主题带键值对的消息消息生产性能优化带分…...

重生归来之挖掘stm32底层知识(1)——寄存器
概念理解 要使用stm32首先要知道什么是引脚和寄存器。 如下图所示,芯片通过这些金属丝与电路板连接,这些金属丝叫做引脚。一般做软件开发是不需要了解芯片是怎么焊的,只要会使用就行。我们平常通过编程来控制这些引脚的输入和输出,…...

Qt构建JSON及解析JSON
目录 一.JSON简介 JSON对象 JSON数组 二.Qt中JSON介绍 QJsonvalue Qt中JSON对象 Qt中JSON数组 QJsonDocument 三.Qt构建JSON数组 四.解析JSON数组 一.JSON简介 一般来讲C类和对象在java中是无法直接直接使用的,因为压根就不是一个规则。但是他们在内存中…...

合宙Air201模组LuatOS扩展功能:温湿度传感器篇!
通过前面几期的学习,同学们的学习热情越来越高。 合宙Air201模组除了支持3种定位方式外,还具有丰富的扩展功能,比如:通过外扩BTB链接方案,最多可支持21个IO接口:SPI、I2C、UART等多种接口全部支持。 本期…...
主流敏捷工具scrum工具
在当今的快速变化和高需求的业务环境中,敏捷开发已经成为许多企业实现快速迭代和响应市场需求的重要方法。而在众多敏捷工具中,选择适合自己团队的工具尤为重要。 今天,我们将对比几款主流的敏捷工具,供参考 1. Leangoo领歌&…...
探索微服务架构:从理论到实践,深度剖析其优缺点
微服务架构(Microservice Architecture)是一种软件开发架构形式,它的核心 思想是将大型应用程序拆分成一组小的服务,每个服务都运行在其独立的进程中,并且 服务与服务之间通过轻量级的通信机制(如HTTP REST…...

2024 年最佳 Chrome 验证码扩展,解决 reCAPTCHA 问题
验证码,特别是 reCAPTCHA,已成为在线安全的不可或缺的一部分。虽然它们在区分人类和机器人方面起着至关重要的作用,但它们也可能成为合法用户和从事网络自动化的企业的主要障碍。无论您是试图简化在线体验的个人,还是依赖自动化工…...
Go语言现代web开发defer 延迟执行
The defer statement will delay the execution of a function until the surrounding function is completed. Although execution is postponed, funciton arguments will be evaluated immediately. defer语句将延迟函数的执行,直到周围的函数完成。虽然执行被延…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...

热烈祝贺埃文科技正式加入可信数据空间发展联盟
2025年4月29日,在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上,可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞,强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...
LangChain【6】之输出解析器:结构化LLM响应的关键工具
文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器?1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...