Clipboard:read() 方法
Baseline 2024 *Newly available
Since June 2024, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.
* Some parts of this feature may have varying levels of support.
Clipboard
接口的 read()
方法可用于请求获取剪贴板的内容,返回将兑现为剪贴板数据的 Promise
。
该方法理论上可以返回任意数据(与只能返回文本的 readText()
不同)。浏览器通常支持读取文本、HTML 和 PNG 图像数据。
语法
read()
read(formats)
参数
formats
可选-
包含以下属性的可选对象:
unsanitized
可选-
包含字符串的数组(
Array
),这些字符串为在从剪贴板读取时不应被净化的数据格式的 MIME 类型。某些浏览器在读取剪贴板数据时可能会对其进行净化,以防止恶意内容被粘贴到文档中。例如,Chrome(及其他基于 Chromium 的浏览器)会通过去除
<script>
标签和其他潜在危险内容来净化 HTML 数据。使用unsanitized
数组可以指定不应被净化的 MIME 类型列表。
返回值
一个将兑现为包含剪贴板内容的 ClipboardItem
对象数组的 Promise
。
异常
NotAllowedError
DOMException
-
如果不允许从剪贴板读取数据,则抛出此异常。
安全考虑
示例
从剪贴板中读取图片
此示例使用 read()
方法从剪贴板读取图像数据并将其粘贴到 <img>
元素中。
HTML
<img id="source" src="butterfly.jpg" alt="A butterfly" />
<img id="destination" />
<button id="reload" type="button">重新加载</button>
<p id="log"></p>
CSS
img {
height: 100px;
width: 100px;
margin: 0 1rem;
border: 1px solid black;
}
#reload {
display: block;
margin: 0 1rem;
}
JavaScript
此代码将任何错误记录到 id 为 log
的元素中。
const logElement = document.querySelector("#log");
function log(text) {
logElement.innerText = `Error: ${text}`;
}
我们还添加了代码,当按下“重新加载”按钮时重新加载并清除示例。
const reload = document.querySelector("#reload");
reload.addEventListener("click", () => {
window.location.reload(true);
});
剩余代码在单击目标元素时读取剪贴板,并将图像数据复制到 destinationImage
元素中。如果无法使用 read()
方法,或者剪贴板不包含 PNG 格式的数据,则记录错误。
const destinationImage = document.querySelector("#destination");
destinationImage.addEventListener("click", pasteImage);
async function pasteImage() {
try {
const clipboardContents = await navigator.clipboard.read();
for (const item of clipboardContents) {
if (!item.types.includes("image/png")) {
throw new Error("剪贴板不包含 PNG 图像数据。");
}
const blob = await item.getType("image/png");
destinationImage.src = URL.createObjectURL(blob);
}
} catch (error) {
log(error.message);
}
}
结果
通过右键单击左侧的显示蝴蝶的图像并从上下文菜单中选择“复制图像”来复制该图像。然后单击右侧的空框。示例将从剪贴板获取图像数据并在空框中显示图像。
备注: 如果出现提示,请授予权限以粘贴图像。
从剪贴板读取数据
此示例使用 read()
方法从剪贴板读取数据并记录剪贴板中存储的任何数据。
这与前一个版本不同,它将显示文本、HTML 和图像 ClipboardItem
对象(而不仅仅是图像)。
HTML
<img id="source_jpg" src="butterfly.jpg" alt="JPG butterfly image" />
<div id="destination">点击此处拷贝剪贴板数据</div>
<button id="reload" type="button">重新加载</button>
<p id="log"></p>
CSS
img {
height: 100px;
width: 100px;
margin: 0 1rem;
border: 1px solid black;
}
#destination {
min-height: 300px;
min-width: 90%;
margin: 0 1rem;
border: 1px solid black;
}
#reload {
display: block;
margin: 0 1rem;
}
JavaScript
此代码将任何错误记录到 id 为 log
的元素中。
const logElement = document.querySelector("#log");
function log(text) {
logElement.innerText = `错误:${text}`;
}
我们还添加了代码,当按下“重新加载”按钮时重新加载并清除示例。
const reload = document.querySelector("#reload");
reload.addEventListener("click", () => {
window.location.reload(true);
});
剩余代码在单击目标元素时读取剪贴板,并显示每个 ClipboardItem
元素及其 MIME 类型。如果无法使用 read()
方法,或者剪贴板包含任何其他 MIME 类型,则记录错误。
const destinationDiv = document.querySelector("#destination");
destinationDiv.addEventListener("click", pasteData);
async function pasteData() {
destinationDiv.innerText = ""; // 清除内部文本
try {
const clipboardContents = await navigator.clipboard.read();
for (const item of clipboardContents) {
for (const mimeType of item.types) {
const mimeTypeElement = document.createElement("p");
mimeTypeElement.innerText = `MIME 类型:${mimeType}`;
destinationDiv.appendChild(mimeTypeElement);
if (mimeType === "image/png") {
const pngImage = new Image(); // Image 构造函数
pngImage.src = "image1.png";
pngImage.alt = "剪贴板中得到的 PNG";
const blob = await item.getType("image/png");
pngImage.src = URL.createObjectURL(blob);
destinationDiv.appendChild(pngImage);
} else if (mimeType === "text/html") {
const blob = await item.getType("text/html");
const blobText = await blob.text();
const clipHTML = document.createElement("pre");
clipHTML.innerText = blobText;
destinationDiv.appendChild(clipHTML);
} else if (mimeType === "text/plain") {
const blob = await item.getType("text/plain");
const blobText = await blob.text();
const clipPlain = document.createElement("pre");
clipPlain.innerText = blobText;
destinationDiv.appendChild(clipPlain);
} else {
throw new Error(`${mimeType} 不被支持。`);
}
}
}
} catch (error) {
log(error.message);
}
}
结果
复制一些文本或下面的蝴蝶(JPG)图像(要复制图像,请右键单击它们,然后从上下文菜单中选择“复制图像”)。选择下面的指示框以将剪贴板中的信息粘贴到框中。
注意:
- 尽管这张显示蝴蝶的图像是 JPG 文件,但从剪贴板读取时它会是 PNG 格式。
- 如果出现提示,你需要授予权限以粘贴图像。
- 这可能在 Chromium 浏览器上不起作用,因为示例框架未授予 Permissions-Policy
clipboard-read
和clipboard-write
权限(Chromium 浏览器要求)。
从剪贴板读取未净化的 HTML
此示例使用 formats
参数从剪贴板读取 HTML 数据,并不让浏览器进行净化以原始形式获取代码。
HTML
<textarea id="source" rows="5">
<style>h1 {color: red;} p {color: blue;}</style>
<h1>你好,世界!</h1>
<p>一个小测试。</p>
<script>alert('你好,世界!');</script>
</textarea>
<button id="copy">复制 HTML</button>
<button id="paste_normal">粘贴 HTML</button>
<button id="paste_unsanitized">粘贴未净化的 HTML</button>
<textarea id="destination" rows="5"></textarea>
CSS
body {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 5px;
}
textarea {
grid-column: 1 / span 3;
}
JavaScript
const copyButton = document.getElementById("copy");
const pasteButton = document.getElementById("paste_normal");
const pasteUnsanitizedButton = document.getElementById("paste_unsanitized");
const sourceTextarea = document.getElementById("source");
const destinationTextarea = document.getElementById("destination");
copyButton.addEventListener("click", async () => {
const text = sourceTextarea.value;
const type = "text/html";
const blob = new Blob([text], { type });
const data = [new ClipboardItem({ [type]: blob })];
try {
await navigator.clipboard.write(data);
} catch (error) {
destinationTextarea.value = `无法写入剪贴板:${error}`;
}
});
async function getHTMLFromClipboardContents(clipboardContents) {
for (const item of clipboardContents) {
if (item.types.includes("text/html")) {
const blob = await item.getType("text/html");
const blobText = await blob.text();
return blobText;
}
}
return null;
}
pasteButton.addEventListener("click", async () => {
try {
const clipboardContents = await navigator.clipboard.read();
const html = await getHTMLFromClipboardContents(clipboardContents);
destinationTextarea.value = html || "剪贴板中无 HTML 数据。";
} catch (error) {
destinationTextarea.value = `无法读取剪贴板:${error}`;
}
});
pasteUnsanitizedButton.addEventListener("click", async () => {
try {
const clipboardContents = await navigator.clipboard.read({
unsanitized: ["text/html"],
});
const html = await getHTMLFromClipboardContents(clipboardContents);
destinationTextarea.value = html || "剪贴板中无 HTML 数据。";
} catch (error) {
destinationTextarea.value = `无法读取剪贴板:${error}`;
}
});
结果
首先单击“复制 HTML”按钮,将第一个文本区域中的 HTML 代码写入剪贴板。然后单击“粘贴 HTML”按钮或“粘贴未净化的 HTML”按钮,将净化或未净化的 HTML 代码粘贴到第二个文本区域中。
规范
Specification |
---|
Clipboard API and events # dom-clipboard-read |
浏览器兼容性
参见
- Clipboard API
- web.dev 上的解锁剪贴板权限
- developer.google.cn 上的异步 Clipboard API 中的未净化的 HTML
Clipboard.readText()
Clipboard.writeText()
Clipboard.write()