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处理中文

热门文章

修复群晖Synology Drive client右键菜单缺失问题 本教程主要解决windows10右键菜单中没有SynologyDrive菜单的问题,整体思路是找到...修复群晖SynologyDriveclient右键菜单缺失问题 作者:Pastore Antonio
1823 浏览量
docker如何查看一个镜像内部的目录结构及其内部都有哪些文件 前言:有时候我们会在docker上下载一个镜像,或者是上传一个镜像到docker上,甚至有时候就是在...docker如何查看一个镜像内部的目录结构及其内部都有哪些文件 作者:Pastore Antonio
1805 浏览量
Adobe Acrobat Pro 激活 这里记录了一些AdobeAcrobat的激活教程和组件。浏览量:1,687 作者:Pastore Antonio
1533 浏览量
configure: error: Package requirements (oniguruma) were not met configure:error:Packagerequirements(oniguruma)...configure:error:Packagerequirements(oniguruma)werenotmet 作者:Pastore Antonio
1533 浏览量
追寻日出,找回自己 为什么我要去追寻日出?其实我是一个很懒的人,每次都起不来,直到有一次我在租房中睡到了大天亮,阳光照...追寻日出,找回自己 作者:Pastore Antonio
1514 浏览量