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

调用REST API获取PNG转Base64后浏览器显示损坏图标问题

解决REST API获取PNG图片后Base64编码显示损坏的问题

嘿,我一眼就看出问题出在哪了——你在处理二进制图片响应的时候,错误地把它当成文本在处理,这直接导致Base64编码乱掉,图片自然显示损坏。咱们来一步步修复:

问题到底出在哪?

后端返回的是原始PNG二进制字节流,但你用http.responseText去接收,这会让浏览器把二进制数据当成UTF-8文本解析,过程中很多字节会被错误转换或丢失。之后再用unescape(encodeURIComponent(...))和btoa折腾一遍,编码出来的Base64肯定不对,图片不损坏才怪。

另外还有两个小坑:

  • 前端设置Access-Control-Allow-Origin请求头完全没用,这个头是后端用来告诉浏览器允许跨域的,前端不需要加
  • 后端@CrossOrigin写的是http://localhost:8080,但你前端跑在8888端口,跨域配置不匹配,搞不好还会先触发跨域错误

修复后的代码

前端JavaScript(推荐用Blob方案,简单高效)

把XHR的响应类型改成blob,直接用浏览器的API处理二进制数据,不用手动搞Base64:

function getcap(){ 
    var http = new XMLHttpRequest() 
    http.open("GET", "http://localhost:8888/newcaptcha", true) 
    // 移除没用的Content-Type和Access-Control请求头
    http.responseType = "blob"; // 关键:告诉XHR接收二进制Blob
    http.send() 
    http.onload = () => { 
        if (http.status === 200) {
            // 直接创建Blob的URL给图片,省得自己编码
            const blobUrl = URL.createObjectURL(http.response);
            const capImg = document.getElementById("capimg");
            capImg.src = blobUrl;
            // 图片加载完记得释放URL,避免内存泄漏
            capImg.onload = () => URL.revokeObjectURL(blobUrl);
        }
    } 
}

如果非要用Base64编码的方式,也可以这么写(用ArrayBuffer处理):

function getcap(){ 
    var http = new XMLHttpRequest() 
    http.open("GET", "http://localhost:8888/newcaptcha", true) 
    http.responseType = "arraybuffer"; 
    http.send() 
    http.onload = () => { 
        if (http.status === 200) {
            // 把ArrayBuffer转成Uint8Array,再转成btoa能处理的字符串
            const uint8Array = new Uint8Array(http.response);
            const binaryStr = String.fromCharCode(...uint8Array);
            const b64Response = window.btoa(binaryStr);
            document.getElementById("capimg").src = `data:image/png;base64,${b64Response}`;
        }
    } 
}

后端Java代码(修正跨域配置)

把跨域允许的地址改成前端实际运行的8888端口:

@CrossOrigin(origins = "http://localhost:8888") // 匹配前端端口
@RequestMapping(value = "/newcaptcha", method = RequestMethod.GET, produces = "image/png") 
public @ResponseBody byte[] getnewCaptcha() { 
    try { 
        Random random = new Random(); 
        imgkey= random.nextInt(3); 
        InputStream is = this.getClass().getResourceAsStream("/"+captcheMap.get(imgkey)+".png"); 
        BufferedImage img = ImageIO.read(is); 
        ByteArrayOutputStream bao = new ByteArrayOutputStream(); 
        ImageIO.write(img, "png", bao); 
        return bao.toByteArray(); 
    } catch (IOException e) { 
        throw new RuntimeException(e); 
    } 
}

为啥这么改?

  • responseType: "blob":让XHR直接保留二进制数据的原样,不会被文本解析破坏
  • URL.createObjectURL():浏览器原生API,生成的URL比手动Base64更高效,还能避免编码错误
  • 跨域配置:后端必须指定前端的实际地址,否则浏览器会拦截跨域请求,连响应都拿不到

内容的提问来源于stack exchange,提问作者jinn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:31:38