JS - 获取剪切板内容 Clipboard API

news2024/11/16 19:56:34

目录

  • 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.1http://localhost

http 环境下是 undefined

在这里插入图片描述

2,只能读取当前页面的剪切板

有5个区域:

  1. 页面内容显示区域
  2. 地址栏
  3. 书签栏
  4. 控制台
  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/plaintext/html

在这里插入图片描述

2,图片内容

1,如果是截图,type 统一为 image/png

在这里插入图片描述

2,如果是从网页上复制的图片(无论原图片是什么格式),type 统一都是2个:text/htmlimage/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>

以上。

参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2133711.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入MySQL的索引实践及优化

文章目录 一、什么是索引二、数据结构——为什么是B树平衡二叉查找树红黑树B树&#xff08;多叉&#xff09;B树&#xff08;多叉&#xff09; 三、MySQL索引实战1.索引创建(1)自动创建索引(2)手动创建非聚簇索引(3)索引的代价 2.B树索引原则&#xff08;1&#xff09;等值匹配…

make 程序规定的 makefile 文件的书写语法(4)

&#xff08;29&#xff09;接着学习 make 支持的变量追加操作&#xff0c; &#xff0c; 在变量的原有字符串的基础上&#xff0c;再追加字符串&#xff0c;并用一个空格隔开&#xff1a; &#xff08;30&#xff09;再学习 make 的语法&#xff0c;shell 运行赋值&#xff1…

关于Redis缓存一致性问题的优化和实践

目录标题 导语正文分布式场景下无法做到强一致即使是达到最终一致性也很难缓存的一致性问题缓存是如何写入的 如何感知数据库的变化最佳实践一&#xff1a;数据库变更后失效缓存最佳实践二&#xff1a;带版本写入 总结与展望阿里XKV腾讯DCache 导语 Redis缓存一致性的问题是经…

大模型→世界模型下的「认知流形」本质·下

本篇内容节选自今年初我撰写的那篇10万的文章《融合RL与LLM思想&#xff0c;探寻世界模型以迈向AGI》&#xff0c;其观点也是文章中核心中的核心。 想进一步完整阅读的小伙伴可关注评论&#xff0c;节选内容如下↓ 接上篇..“因此当前无论对先验自回归学习下的LLMs也好还是未来…

ASR(自动语音识别)识别文本效果的打分总结

ASR(自动语音识别)识别文本效果的打分总结 1. 词错误率(WER, Word Error Rate)2. 字正确率(W.Corr, Word Correct)3. 编辑距离(Edit Distance)4. 特定错误率5. 句子错误率(SER, Sentence Error Rate)6. 基于模型的评估方法对于ASR(自动语音识别)识别文本效果的打分…

【python】python中非对称加密算法RSA实现原理与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

9.13 DFSBFS 简单 101 Symmetric Tree 104 Maximum Depth of Binary Tree

101 Symmetric Tree class Solution { public:// 比较两个向量是否镜像对称bool isIdentical(const std::vector<int>& n1, const std::vector<int>& n2) {int n n1.size();for (int i 0; i < n; i) {if (n1[i] ! n2[n - i - 1]) return false; // 镜…

AV1 Bitstream Decoding Process Specification--[2]:符号和缩写术语

原文地址&#xff1a;https://aomediacodec.github.io/av1-spec/av1-spec.pdf没有梯子的下载地址&#xff1a;AV1 Bitstream & Decoding Process Specification摘要&#xff1a;这份文档定义了开放媒体联盟&#xff08;Alliance for Open Media&#xff09;AV1视频编解码器…

通过LiveGBS实现安防监控摄像头GB28181转成WebRTC流实现web浏览器网页无插件低延迟直播...

目录 1、WebRTC超低延时直播2、WebRTC延时对比3、LiveGBS的低延时的WebRTC流4、分屏页面如何选择默认播放流5、无法播放Webrtc6、搭建GB28181视频直播平台 1、WebRTC超低延时直播 需要低延时的视频流监控播放&#xff0c;之前可以用rtmp的低延时播放(1秒左右)&#xff0c;随着浏…

三星ZFlip5/ZFlip4/W7024刷安卓14国行OneUI6.1系统-高级设置-韩/欧/港版

三星ZFlip5/ZFlip4/W7024系列手机&#xff0c;基本都是高端玩家的一个产品&#xff0c;目前虽然国内销量不 如其他品牌&#xff0c;但依旧表现不错&#xff0c;并且大家都不知道三星全球第一&#xff0c;自然在国外销量也比较OK 由于三星全部设备基本都支持解锁BL&#xff08;美…

Spring Boot基础

项目创建 项目启动 请求响应 RestController 1.返回值处理 RestController&#xff1a;这个注解结合了Controller和ResponseBody的功能。它默认将所有处理请求的方法的返回值直接作为响应体内容返回&#xff0c;主要用于构建RESTful API。返回的数据格式通常是JSON或XML&…

vue使用TreeSelect设置带所有父级节点的回显

Element Plus的el-tree-select组件 思路&#xff1a; 选中节点时&#xff0c;给选中的节点赋值 pathLabel&#xff0c;pathLabel 为函数生成的节点名字拼接&#xff0c;数据源中不包含。 在el-tree-select组件中设置 props“{ label: ‘pathLabel’ }” 控制选中时input框中回…

商务办公tips1:如何将网页转换为pdf

​ 场景需求&#xff1a; 商务轻办公人士获取网页内容&#xff0c;并且最好是pdf版本&#xff1f; 将网页转换为PDF的需求可能出现在多种场景中&#xff0c;以下是一些可能的情况&#xff1a; 学术研究&#xff1a;研究人员可能需要将某个学术网站的全文内容保存为PDF格式&a…

sqlgun靶场训练

1.看到php&#xff1f;id &#xff0c;然后刚好有个框&#xff0c;直接测试sql注入 2.发现输入1 union select 1,2,3#的时候在2处有回显 3.查看表名 -1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schemadatabase()# 4.查看列名…

【计网】从零开始使用UDP进行socket编程 --- 客户端与服务端的通信实现

人生不过如此&#xff0c;且行且珍惜。 自己永远是自己的主角&#xff0c; 不要总在别人的戏剧里充当着配角。 --- 林语堂 --- 从零开始学习socket编程---UDP协议 1 客户端与服务端的通信2 设计UDP服务器类2.1 基础框架设计2.2 初始化函数2.3 启动函数 3 设计客户端 1 客户…

会员计次卡渲染技术-—SAAS本地化及未来之窗行业应用跨平台架构

一、计次卡应用 1. 健身中心&#xff1a;会员购买一定次数的健身课程或使用健身房设施的权限。 2. 美容美发店&#xff1a;提供一定次数的理发、美容护理等服务。 3. 洗车店&#xff1a;车主购买若干次的洗车服务。 4. 儿童游乐场&#xff1a;家长为孩子购买固定次数的入场游…

分类预测|基于差分优化DE-支持向量机数据分类预测完整Matlab程序 DE-SVM

分类预测|基于差分优化DE-支持向量机数据分类预测完整Matlab程序 DE-SVM 文章目录 一、基本原理DE-SVM 分类预测原理和流程总结 二、实验结果三、核心代码四、代码获取五、总结 一、基本原理 DE-SVM 分类预测原理和流程 1. 差分进化优化算法&#xff08;DE&#xff09; 原理…

跟《经济学人》学英文:2024年09月07日这期 How fashion conquered television

How fashion conquered television More and more shows celebrate fancy clothes. Often brands call the shots 原文&#xff1a; From Tokyo to Seoul, on to New York, London, Milan and Paris, there are more “fashion weeks” in September than there are weeks i…

【Pandas操作2】groupby函数、pivot_table函数、数据运算(map和apply)、重复值清洗、异常值清洗、缺失值处理

1 数据清洗 #### 概述数据清洗是指对原始数据进行处理和转换&#xff0c;以去除无效、重复、缺失或错误的数据&#xff0c;使数据符合分析的要求。#### 作用和意义- 提高数据质量&#xff1a;- 通过数据清洗&#xff0c;数据质量得到提升&#xff0c;减少错误分析和错误决策。…

sharding-jdbc metadata load优化(4.1.1版本)

背景 系统启动时&#xff0c;会注意sharding-jdbc提示加载metadata 于是想看看里面做了什么事情 问题追踪 debug后可以观察走到了该类 org.apache.shardingsphere.shardingjdbc.jdbc.core.context.ShardingRuntimeContext#loadSchemaMetaData 先看这个shardingRuntimeConte…