IE中Angular将Base64转字节数组:PDF打开损坏问题排查
问题分析与解决方法
你的问题出在二进制数据的编码转换环节,导致PDF的原始字节流被破坏,具体原因和修复方案如下:
为什么之前的代码会导致文件损坏?
Buffer不是浏览器原生API:你使用的Buffer是Node.js的专属对象,浏览器环境下没有原生支持,即使引入第三方polyfill,Buffer.toString('binary')的处理逻辑在IE中会把二进制数据转换成字符串,后续将这个字符串传入Blob时,Blob会默认按UTF-8编码重新转换为字节——但PDF的字节流并非UTF-8编码的文本,这种转码操作会直接破坏文件的原始二进制结构。toString('binary')的编码兼容性问题:所谓的"binary"编码在不同环境下实现不一致,浏览器中并没有标准的"binary"编码规范,这个操作本质是把字节转成了Latin-1编码的字符串,而Blob处理时又会用UTF-8解析,双重编码错误直接导致文件损坏。
针对IE的正确解决方案
我们需要直接将Base64解码为原始的字节数组(Uint8Array),再用这个数组创建Blob,完整保留PDF的二进制数据。同时兼容IE可能不支持atob的情况:
代码实现
// 兼容IE的Base64解码函数(替代atob,支持IE9及以下) function decodeBase64(base64Str) { const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; let output = ""; // 过滤Base64字符串中的非法字符 base64Str = base64Str.replace(/[^A-Za-z0-9\+\/\=]/g, ""); for (let i = 0; i < base64Str.length; i += 4) { const enc1 = chars.indexOf(base64Str.charAt(i)); const enc2 = chars.indexOf(base64Str.charAt(i + 1)); const enc3 = chars.indexOf(base64Str.charAt(i + 2)); const enc4 = chars.indexOf(base64Str.charAt(i + 3)); const chr1 = (enc1 << 2) | (enc2 >> 4); const chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); const chr3 = ((enc3 & 3) << 6) | enc4; output += String.fromCharCode(chr1); if (enc3 !== 64) output += String.fromCharCode(chr2); if (enc4 !== 64) output += String.fromCharCode(chr3); } return output; } // 主处理逻辑 const b64Data = myBase64Url.split(',', 2)[1]; // 如果仅支持IE10+,可以直接用 window.atob(b64Data) 替代 decodeBase64 const binaryString = decodeBase64(b64Data); // 将二进制字符串转换为Uint8Array字节数组 const byteArray = new Uint8Array(binaryString.length); for (let j = 0; j < binaryString.length; j++) { byteArray[j] = binaryString.charCodeAt(j); } // 用字节数组创建Blob,调用IE专属API保存/打开 const blob = new Blob([byteArray], { type: 'application/pdf' }); window.navigator.msSaveOrOpenBlob(blob);
关键说明
- 直接操作
Uint8Array字节数组,避免了字符串编码转换带来的字节丢失问题,Blob会直接使用这个数组的原始二进制数据。 - 自定义的
decodeBase64函数完全兼容IE9及更低版本,若只需支持IE10+,直接替换成window.atob(b64Data)即可简化代码。
内容的提问来源于stack exchange,提问作者hakuna
相关产品推荐
相关产品推荐

