剪贴板:read() 方法
Clipboard
接口的 read()
方法请求剪贴板内容的副本,并在返回的 Promise
中使用数据完成。
理论上,该方法可以返回任意数据(不像 readText()
,它只能返回文本)。浏览器通常支持读取文本、HTML 和 PNG 图像数据 - 请参阅 浏览器兼容性 了解更多信息。
语法
read()
read(formats)
参数
formats
可选-
具有以下属性的可选对象
unsanitized
可选-
包含应在从剪贴板读取时不应进行清理的 MIME 类型数据的字符串的
Array
。某些浏览器可能会在读取剪贴板数据时对其进行清理,以防止恶意内容粘贴到文档中。例如,Chrome(和其他基于 Chromium 的浏览器)会通过剥离
<script>
标签和其他潜在的危险内容来清理 HTML 数据。使用unsanitized
数组指定不应进行清理的 MIME 类型列表。
返回值
一个 Promise
,它解析为包含剪贴板内容的 ClipboardItem
对象数组。
异常
NotAllowedError
DOMException
-
如果不允许从剪贴板读取,则抛出此异常。
安全注意事项
示例
从剪贴板读取图像数据
此示例使用 read()
方法从剪贴板读取图像数据,并将其粘贴到 <img>
元素中。
HTML
<img id="source" src="butterfly.jpg" alt="A butterfly" />
<img id="destination" />
<button id="reload" type="button">Reload</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("Clipboard does not contain PNG image data.");
}
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">Click here to copy clipboard data.</div>
<button id="reload" type="button">Reload</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 = `Error: ${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 = ""; //Clear inner text
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 type: ${mimeType}`;
destinationDiv.appendChild(mimeTypeElement);
if (mimeType === "image/png") {
const pngImage = new Image(); // Image constructor
pngImage.src = "image1.png";
pngImage.alt = "PNG image from clipboard";
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} not supported.`);
}
}
}
} 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>Hello world!</h1>
<p>This is a test.</p>
<script>alert('Hello world!');</script>
</textarea>
<button id="copy">Copy HTML</button>
<button id="paste_normal">Paste HTML</button>
<button id="paste_unsanitized">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 = `Clipboard write failed: ${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 || "Could not find HTML data in the clipboard.";
} catch (error) {
destinationTextarea.value = `Clipboard read failed: ${error}`;
}
});
pasteUnsanitizedButton.addEventListener("click", async () => {
try {
const clipboardContents = await navigator.clipboard.read({
unsanitized: ["text/html"],
});
const html = await getHTMLFromClipboardContents(clipboardContents);
destinationTextarea.value =
html || "Could not find HTML data in the clipboard.";
} catch (error) {
destinationTextarea.value = `Clipboard read failed: ${error}`;
}
});
结果
首先单击“复制 HTML”按钮,将第一个文本区域中的 HTML 代码写入剪贴板。然后,单击“粘贴 HTML”按钮或“粘贴未清理的 HTML”按钮,将清理后的或未清理的 HTML 代码粘贴到第二个文本区域中。
规范
规范 |
---|
剪贴板 API 和事件 # dom-clipboard-read |
浏览器兼容性
BCD 表格仅在浏览器中加载
另请参阅
- 剪贴板 API
- 解除剪贴板访问的阻塞 on web.dev
- 异步剪贴板 API 中的未清理 HTML on developer.chrome.com
Clipboard.readText()
Clipboard.writeText()
Clipboard.write()