获取剪切板的图片 -> File -> Base64 -> Blob -> url -> Image,以及它们之间的各种相互转换

🧑‍💻 写在开头

点赞 + 收藏 === 学会🤣🤣🤣

一、获取剪切板的图片(拿到 File 对象)

js粘贴事件paste简单解析及遇到的坑 - 云+社区 - 腾讯云 (tencent.com)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
document.addEventListener('paste', function(event) {
    let items = event.clipboardData && event.clipboardData.items;
    let file: any = null;
    if (items && items.length) {
        // 检索剪切板items
        for (var i = 0; i < items.length; i++) {
            if (items[i].type.indexOf('image') !== -1) {
                file = items[i].getAsFile();
                break;
            }
        }
    }
    fileByBase64(file, (base64) => {
        shotCallback(base64);
    });
    console.log('file', file);
    // 此时file就是剪切板中的图片文件
});

本来想直接获取这个对象的,然鹅这个 clipboardData 对象只存在于 ClipboardEvent 事件中,只能在事件(这里是 parse 事件)触发的时候才能拿到。

ClipboardEvent.clipboardData - Web API 接口参考 | MDN (mozilla.org)

题外话:可以直接用 navigator.clipboard 获取到剪切板内容(拿到 Blob 对象)

Navigator.clipboard - Web API 接口参考 | MDN (mozilla.org)

剪贴板操作 Clipboard API 教程 - 阮一峰的网络日志 (ruanyifeng.com)

1
2
3
4
5
6
7
8
9
const getClipboard = async () => {
    const clipboardItems = await navigator.clipboard.read();
    for (const clipboardItem of clipboardItems) {
        for (const type of clipboardItem.types) {
            const blob = await clipboardItem.getType(type);
            console.log(URL.createObjectURL(blob));
        }
    }
};

二、File 对象转 Base64(利用 FileReader)

1
2
3
4
5
6
7
8
9
10
const fileByBase64 = (file, callback) => {
    const reader = new FileReader();
    // 传入一个参数对象即可得到基于该参数对象的文本内容
    reader.readAsDataURL(file);
    reader.onload = function(e: any) {
        // target.result 该属性表示目标对象的 DataURL
        console.log(e.target.result);
        callback(e.target.result);
    };
};

题外话 canvas -> dataUrl(Base64)

才发现 Base64 是 DataUrl 的编码,可以理解为一种东西吧。

canvas 对象可以直接转变成 base64,有一个很常用的 api:

1
const dataURL = canvas.toDataURL();

三、Base64 转 Blob

1
2
3
4
5
6
7
8
9
10
11
12
const base64ByBlob = (base64, callback) => {
    let arr = base64.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }
    console.log(new Blob([u8arr], { type: mime }));
    callback(new Blob([u8arr], { type: mime }));
};

题外话:Blob -> Base64(利用 FileReader)

由于 File 是特殊类型的 Blob,所以跟 File -> Base64 是一样的。

1
2
3
4
5
6
7
function blobToDataURI(blob, callback) {
    var reader = new FileReader();
    reader.onload = function (e) {
        callback(e.target?.result);
    };
    reader.readAsDataURL(blob);
}

题外话:File <--> Blob

它俩可以用构造函数直接相互转换,没有中间商 Base64。不过 file -> blob 会丢失 filename。

1
2
3
const blob = new Blob([file], {
    type: file.type
}
1
2
3
const file = new File([blob], filename, {
    type: blob.type
});

四、blob 转 url、file 转 url

1
2
const url1 = window.URL.createObjectURL(blob);
const url2 = window.URL.createObjectURL(file);

这里的 file 会被当做 blob 对象来使用,毕竟 file 是特殊的 blob,所以输出结果都是:

1
blob:http://localhost:3000/1df14e9d-b9d3-43d5-87ff-2f7c0ae44a9d

这种由 blob:http:// 开头的路径。

题外话:url -> blob

1
2
3
4
5
const urlToBlob = () => {
    fetch(url)
        .then((res) => res.blob())
        .then((blob) => console.log(blob));
};

五、url 变 Image

1
2
const img = new Image();
img.src = url;

综合应用:获取剪切板图片并转成 Base64,然后 Base64 转成 Blob,然后 Blob 转成 url,然后转成图片 append 到 body 上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
document.addEventListener('paste', function(event) {
    let items = event.clipboardData && event.clipboardData.items;
    console.log('items', items);
    let file: any = null;
    if (items && items.length) {
        // 检索剪切板 items
        for (var i = 0; i < items.length; i++) {
            if (items[i].type.indexOf('image') !== -1) {
                // 此时file就是剪切板中的图片文件
                file = items[i].getAsFile();
                break;
            }
        }
    }
    fileByBase64(file, base64 => {
        base64ByBlob(base64, (blob) => {
            const url = window.URL.createObjectURL(blob);
            console.log('url', url);
            const img = new Image();
            img.src = url;
            img.onload = () => {
                document.body.appendChild(img);
            };
        });
    });
});

如果不需要额外使用 Base64 的话,直接用 file 对象替代 blob 也是可以的,因为 file 只是特殊的 blob,大家都是二进制文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
document.addEventListener('paste', function(event) {
    let items = event.clipboardData && event.clipboardData.items;
    console.log('items', items);
    let file: any = null;
    if (items && items.length) {
        // 检索剪切板 items
        for (var i = 0; i < items.length; i++) {
            if (items[i].type.indexOf('image') !== -1) {
                // 此时file就是剪切板中的图片文件
                file = items[i].getAsFile();
                break;
            }
        }
    }
    const url = window.URL.createObjectURL(file);
    console.log('url', url);
    const img = new Image();
    img.src = url;
    img.onload = () => {
        document.body.appendChild(img);
    };
});

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

posted @   林恒  阅读(156)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· 【全网最全教程】使用最强DeepSeekR1+联网的火山引擎,没有生成长度限制,DeepSeek本体
历史上的今天:
2020-12-03 uni-app开发经验分享九: 组件传值
2020-12-03 uni-app开发经验分享八: 实现微信APP支付的全过程详解
欢迎阅读『获取剪切板的图片 -> File -> Base64 -> Blob -> url -> Image,以及它们之间的各种相互转换』
点击右上角即可分享
微信分享提示