引言
在现代Web应用程序中,上传图片是一个常见的功能。通常,用户需要通过选择文件或拖放文件来上传图片。然而,有些情况下,用户可能更希望直接从剪贴板粘贴图片。本文将介绍如何使用JavaScript实现粘贴上传图片的功能。
使用Clipboard API
在JavaScript中,可以使用navigator.clipboard.readText()
方法来从剪贴板读取文本数据。但是,如果拷贝的是图片的话,是无法通过这个方法获取的,我们可以使用navigator.clipboard.read
方法,使用时请注意该方法是一个异步方法。
navigator.clipboard.read()
返回的是一个包含 ClipboardItem
对象的数组,我们需要使用 ClipboardItem.types
属性来获取类型,然后使用 ClipboardItem.getType()
方法来获取 Blob 对象,使用示例如下:
navigator.clipboard.read().then(async (data)=>{
for (const clipboardItem of data) {
const {types} = clipboardItem
for (const type of types) {
if(type.indexOf('image')!=-1) {
const blob = await clipboardItem.getType(type)
let reader = new FileReader()
reader.onload=(e)=>{
// e.target?.result 为图片对应的base64,在此处可以进行图片的上传操作
console.log(e.target?.result)
}
reader.readAsDataURL(blob)
}
}
}
}).catch(err=>{
console.error('Could not read from clipboard: ', err);
})
这种方式主要用于主动触发粘贴行为,例如点击粘贴按钮时,调用方法进行图片的粘贴或者上传。
以下是一个简单的试验:
<div>显示粘贴的图片:<img id="image"/></div>
<button onclick="pasteImage()">粘贴图片</button>
async function pasteImage() {
const textContent = document.getElementById('text')
navigator.clipboard.read().then(async (data)=>{
for (const clipboardItem of data) {
const {types} = clipboardItem
for (const type of types) {
if(type.indexOf('image')!=-1) {
const blob = await clipboardItem.getType(type)
let reader = new FileReader()
reader.onload=(e)=>{
document.getElementById('image').setAttribute('src',e.target.result)
}
reader.readAsDataURL(blob)
}
}
}
}).catch(err=>{
console.error('Could not read from clipboard: ', err);
})
}
剪切板上的截图图片如下:
点击粘贴按钮后的效果:
使用paste事件
在JavaScript中,我们可以监听paste事件来获取用户粘贴的内容。如果用户粘贴的内容中包含图片,我们可以读取这个图片并将其上传到服务器。这个应用场景也是比较多的,例如CSDN在写博客的时候,可以直接将粘贴图片,会自动上传到csdn生成一个图片链接一样。
以下是一个基本的实现:
document.addEventListener('paste', function (event) {
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
for (var index in items) {
var item = items[index];
if (item.kind === 'file') {
var blob = item.getAsFile();
var reader = new FileReader();
reader.onload = function(event){
console.log(event.target.result); // 这里是图片的base64编码
// 你可以在这里将图片上传到服务器
};
reader.readAsDataURL(blob);
}
}
});
这段代码会监听粘贴事件,如果粘贴的内容中有文件(在这种情况下,我们关心的是图片),它会读取该文件并将其转换为base64编码。然后你可以将这个编码上传到服务器。
一个简单的使用小示例:
<div class="editor" contenteditable="true"></div>
const editor = document.getElementById('editor')
editor.onpaste = function (event) {
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
for (var index in items) {
var item = items[index];
if (item.kind === 'file') {
var blob = item.getAsFile();
var reader = new FileReader();
reader.onload = function(event){
console.log(event.target.result); // 这里是图片的base64编码
//这里是在前端显示图片,可以自由操作是上传后端还是进行文件操作
insertImageByLink(event.target.result)
};
reader.readAsDataURL(blob);
}
}
}
function insertImageByLink(link) {
const image = new Image()
image.src = link
const selection = window.getSelection()
const range = selection.getRangeAt(0)
range.insertNode(image)
range.setStartAfter(image)
}
在文本框中,按下ctrl+v进行粘贴,可将图片粘贴并显示到文本框中
可以对拿到的blob进行以下几种常规操作
//创建blob url
function createTempImage(blob) {
const url = window.URL.createObjectURL(blob)
insertImageByLink(url)
}
async function uploadImage(base64) {
// 接口上传到后台服务器
}
// blob上传
function createServerImage(blob) {
const reader = new FileReader()
reader.onload = (e)=>{
const base64 = e.target.result
// 上传base64到后台服务器生成url
const url = await uploadImage(base64)
insertImageByLink(url)
}
reader.readAsDataURL(blob)
}
function insertImageByLink(link) {
const image = new Image()
image.src = link
const selection = window.getSelection()
const range = selection.getRangeAt(0)
range.insertNode(image)
range.setStartAfter(image)
}
总结
在JavaScript中,我们有多种方法可以实现粘贴上传图片的功能。你可以根据你的需求和目标浏览器的支持情况来选择最适合你的方法。无论你选择哪种方法,都要记住处理错误,并尽可能提供良好的用户体验。