You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将可编辑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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:54:31