如何将可编辑div中粘贴图片的Blob src转为Data URI?
解决Safari中Blob格式图片转Base64 Data URI的问题
我明白你在Mac Safari里遇到的问题了——粘贴到contenteditable的图片返回的是Blob URL,没法直接拿到Base64格式。别担心,我们可以通过先获取Blob对象再用FileReader转码的方式解决这个问题,下面是具体的方案和代码修改:
核心思路
Blob URL是浏览器为内存中的Blob对象生成的临时引用,要转成Base64,我们需要:
- 用
fetch()请求这个Blob URL,拿到对应的Blob数据 - 用
FileReader的readAsDataURL()方法把Blob转成Base64格式的Data URI
修改你的代码
主要需要修正checkInput函数里错误的FileReader用法(你之前直接把Blob URL传给了readAsDataURL,但它需要的是Blob/File对象),修改后的代码如下:
// We start by checking if the browser supports the // Clipboard object. If not, we need to create a // contenteditable element that catches all pasted data if (!window.Clipboard) { var pasteCatcher = document.createElement("div"); // Firefox allows images to be pasted into contenteditable elements pasteCatcher.setAttribute("contenteditable", ""); // We can hide the element and append it to the body, pasteCatcher.style.opacity = 0.5; document.body.appendChild(pasteCatcher); // as long as we make sure it is always in focus pasteCatcher.focus(); document.addEventListener("click", function() { pasteCatcher.focus(); }); } // Add the paste event listener window.addEventListener("paste", pasteHandler); /* Handle paste events */ function pasteHandler(e) { // We need to check if event.clipboardData is supported (Chrome) if (e.clipboardData) { // Get the items from the clipboard var items = e.clipboardData.items || e.clipboardData.files; var itemcount = items ? items.length : 0; pasteArea.value = "items found:"+itemcount; if (itemcount) { // Loop through all items, looking for any kind of image for (var i = 0; i < items.length; i++) { if (items[i].type.indexOf("image") !== -1) { // We need to represent the image as a file, var blob = items[i].getAsFile(); // 可选:直接在这里转Base64,不用生成Blob URL const reader = new FileReader(); reader.onloadend = function(e) { console.log("Chrome端Base64结果:", e.target.result); createImage(e.target.result); }; reader.readAsDataURL(blob); // 原有的生成Blob URL代码可以保留,也可以替换成上面的逻辑 // var URLObj = window.URL || window.webkitURL; // var source = URLObj.createObjectURL(blob); // createImage(source); } } } else { console.log("no items found. checking input"); // This is a cheap trick to make sure we read the data // AFTER it has been inserted. setTimeout(checkInput, 1); } // If we can't handle clipboard data directly (Firefox), // we need to read what was pasted from the contenteditable element } else { console.log("checking input"); // This is a cheap trick to make sure we read the data // AFTER it has been inserted. setTimeout(checkInput, 1); } } /* Parse the input in the paste catcher element */ function checkInput() { console.log("check input"); // Store the pasted content in a variable var child = pasteCatcher.childNodes[0]; // Clear the inner html to make sure we're always // getting the latest inserted content //pasteCatcher.innerHTML = ""; //console.log( "clearing catcher"); console.log(child); if (child) { // If the user pastes an image, the src attribute // will represent the image as a base64 encoded string. if (child.tagName === "IMG") { createImage(child.src); // 修正:通过fetch获取Blob再转Base64 fetch(child.src) .then(response => response.blob()) .then(blob => { const reader = new FileReader(); reader.onloadend = function(e) { console.log("Safari端Base64结果:", e.target.result); pasteArea.value = e.target.result; }; reader.readAsDataURL(blob); }) .catch(err => console.error("转码失败:", err)); } } } /* Creates a new image from a given source */ function createImage(source) { var pastedImage = new Image(); pastedImage.onload = function(e) { //pasteArea.text = pastedImage.src; console.log(1); console.log(e); loadImage.src = e.target.src; console.log(loadImage.src); } pastedImage.src = source; }
对应的HTML部分保持不变:
<textarea id="pasteArea" placeholder="Paste Image Here"></textarea> <img id="loadImage" />
关键细节说明
fetch(child.src):向Blob URL发起请求,浏览器会直接从内存中读取对应的Blob数据,不会发起实际网络请求response.blob():把响应转换成Blob对象,供FileReader处理FileReader.readAsDataURL(blob):将Blob编码为Base64格式的Data URI,完成后触发onloadend事件,结果存在e.target.result里- 针对Chrome等支持
clipboardData.items的浏览器,我们可以直接在pasteHandler里把拿到的Blob转成Base64,省去生成Blob URL的步骤
这个方案在Mac Safari中可以正常工作,因为fetch和FileReader都是Safari早已支持的标准API。
内容的提问来源于stack exchange,提问作者1.21 gigawatts
相关产品推荐
相关产品推荐

