获取剪切板的图片 -> 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 对象)
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); }; }); |
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
分类:
前端基础知识合集
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· 【全网最全教程】使用最强DeepSeekR1+联网的火山引擎,没有生成长度限制,DeepSeek本体
2020-12-03 uni-app开发经验分享九: 组件传值
2020-12-03 uni-app开发经验分享八: 实现微信APP支付的全过程详解