Logo

使用JavaScript实现粘贴上传图片

photo

2024年03月27日

引言

在现代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中,我们有多种方法可以实现粘贴上传图片的功能。你可以根据你的需求和目标浏览器的支持情况来选择最适合你的方法。无论你选择哪种方法,都要记住处理错误,并尽可能提供良好的用户体验。

橙子主题打折出售

其实我不卖,主要是这里是放广告的,所以就放了一个
毕竟主题都没做完,卖了也是坑.

购买它
本文为原创文章,请注意保留出处!

调用封装的接口,需要转为json格式,使用json_encode(),但是传递的中文被编码了,...PHP的json_encode处理中文

热门文章

ffmpeg 生成水印 1:先要配置ffmpeg的滤镜:参考:https://www.jianshu.com/p/9d24...ffmpeg生成水印 作者:Pastore Antonio
1533 浏览量
Navicat Premium 12.0.22 安装与破解 一、安装  NavicatPremium12.0.22的下载链接:https://pan.ba...NavicatPremium12.0.22安装与破解 作者:Pastore Antonio
1474 浏览量
谷歌浏览器扩展程序报错 The message port closed before a response was received. 问题描述ChromeExtension报错:Uncheckedruntime.lastEr...谷歌浏览器扩展程序报错Themessageportclosedbeforearesponsewasreceived. 作者:Pastore Antonio
1469 浏览量
Spring Aop AfterReturning接收返回值 包结构:Spring.xmlUserDao.java测试类Main方法...SpringAopAfterReturning接收返回值 作者:Pastore Antonio
1464 浏览量
CentOS 系统yum安装出现“未找到匹配的参数”、“没有可用软件包”错误的解决办法 帮助文档链接:https://www.opsit.cn/4896.html今天安装fwknop时,...CentOS系统yum安装出现“未找到匹配的参数”、“没有可用软件包”错误的解决办法 作者:Pastore Antonio
1459 浏览量