剪贴板:read() 方法

基线 2024

新功能

2024 年 6 月起,此功能在所有最新的设备和浏览器版本中都可以使用。此功能可能无法在旧设备或浏览器中使用。

安全上下文:此功能仅在 安全上下文 (HTTPS) 中可用,在一些或所有 支持的浏览器 中。

Clipboard 接口的 read() 方法请求剪贴板内容的副本,并在返回的 Promise 中使用数据完成。

理论上,该方法可以返回任意数据(不像 readText(),它只能返回文本)。浏览器通常支持读取文本、HTML 和 PNG 图像数据 - 请参阅 浏览器兼容性 了解更多信息。

语法

js
read()
read(formats)

参数

formats 可选

具有以下属性的可选对象

unsanitized 可选

包含应在从剪贴板读取时不应进行清理的 MIME 类型数据的字符串的 Array

某些浏览器可能会在读取剪贴板数据时对其进行清理,以防止恶意内容粘贴到文档中。例如,Chrome(和其他基于 Chromium 的浏览器)会通过剥离 <script> 标签和其他潜在的危险内容来清理 HTML 数据。使用 unsanitized 数组指定不应进行清理的 MIME 类型列表。

返回值

一个 Promise,它解析为包含剪贴板内容的 ClipboardItem 对象数组。

异常

NotAllowedError DOMException

如果不允许从剪贴板读取,则抛出此异常。

安全注意事项

只能在 安全上下文 中从剪贴板读取。

API 概述主题的 安全注意事项 部分介绍了其他安全要求。

示例

从剪贴板读取图像数据

此示例使用 read() 方法从剪贴板读取图像数据,并将其粘贴到 <img> 元素中。

HTML

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

css
img {
  height: 100px;
  width: 100px;
  margin: 0 1rem;
  border: 1px solid black;
}
#reload {
  display: block;
  margin: 0 1rem;
}

JavaScript

此代码提供了一种机制,可以将任何错误记录到 id 为 log 的元素中。

js
const logElement = document.querySelector("#log");
function log(text) {
  logElement.innerText = `Error: ${text}`;
}

我们还添加了代码,以便在按下“重新加载”按钮时重新加载并清除示例。

js
const reload = document.querySelector("#reload");

reload.addEventListener("click", () => {
  window.location.reload(true);
});

其余代码在单击目标元素时读取剪贴板,并将图像数据复制到 destinationImage 元素中。如果无法使用 read() 方法,或者剪贴板中不包含 PNG 格式的数据,它将记录错误。

js
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

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

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 的元素中。

js
const logElement = document.querySelector("#log");
function log(text) {
  logElement.innerText = `Error: ${text}`;
}

我们还添加了代码,以便在按下“重新加载”按钮时重新加载并清除示例。

js
const reload = document.querySelector("#reload");

reload.addEventListener("click", () => {
  window.location.reload(true);
});

其余代码在单击目标元素时读取剪贴板,并显示每个 ClipboardItem 元素及其 MIME 类型。如果无法使用 read() 方法,或者剪贴板包含任何其他 MIME 类型,它将记录错误。

js
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-readclipboard-write 权限(Chromium 浏览器要求)。

从剪贴板读取未清理的 HTML

此示例使用 formats 参数从剪贴板读取 HTML 数据,并在浏览器进行清理之前获取原始形式的代码。

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

css
body {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 5px;
}

textarea {
  grid-column: 1 / span 3;
}

JavaScript

js
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 表格仅在浏览器中加载

另请参阅