Clipboard: read() 方法
Baseline 2024 *
新推出
Clipboard 介面的 read() 方法請求複製剪貼簿的內容,並使用返回的 Promise 來處理資料。
理論上,該方法可以返回任意資料(與只能返回文字的 readText() 不同)。瀏覽器通常支援讀取文字、HTML 和 PNG 影像資料。
語法
read()
read(formats)
引數
formats可選-
一個可選物件,具有以下屬性:
unsanitized可選-
一個包含 MIME 型別的字串
Array,這些 MIME 型別的資料格式在從剪貼簿讀取時將不被清理。某些瀏覽器在讀取剪貼簿資料時可能會對其進行清理,以防止惡意內容被貼上到文件中。例如,Chrome(及其他基於 Chromium 的瀏覽器)會透過移除
<script>標籤和其他潛在危險內容來清理 HTML 資料。使用unsanitized陣列可以指定一組不應被清理的 MIME 型別。
返回值
一個 Promise,它將解析為一個 ClipboardItem 物件陣列,其中包含剪貼簿的內容。
異常
NotAllowedErrorDOMException-
如果在剪貼簿讀取過程中不允許,則丟擲此異常。
安全注意事項
剪貼簿讀取只能在 安全上下文 中進行。
其他安全要求已在 API 概述主題的 安全注意事項 部分介紹。
示例
從剪貼簿讀取影像資料
此示例使用 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();
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 程式碼貼上到第二個文字區域中。
規範
| 規範 |
|---|
| Clipboard API 和事件 # dom-clipboard-read |
瀏覽器相容性
載入中…
另見
- Clipboard API
- 解除剪貼簿訪問限制 on web.dev
- 非同步剪貼簿 API 中的未經過濾 HTML on developer.chrome.com
Clipboard.readText()Clipboard.writeText()Clipboard.write()