JavaScript中Unhexlify转换字节失效导致文件损坏问题求助
问题描述
需要从Python向JavaScript传输Excel文件,受约束必须转为字符串传输。Python端读取Excel文件字节并转为十六进制字符串的代码如下:
with open(EXCEL_TEMPLATE_OUTPUTS, "rb") as f: encrypted_bytes = f.read() return encrypted_bytes.hex()
在JavaScript端将十六进制字符串转回字节数组以创建Blob时,使用的函数存在问题:
var unhexlify = function(str) { var bytes = []; for (var i=0, l=str.length; i<l; i+=2) { bytes.push(String.fromCharCode(parseInt(str.substr(i, 2), 16))); } return bytes; }
该函数多数情况正常,但部分字节转换错误,例如十六进制值"c8"被转换为字符"È"而非原始字节"\xc8",导致重建的文件损坏。
示例验证:
- JavaScript代码:
console.log(String.fromCharCode(parseInt("c8", 16)));
输出为"È"而非"\xc8";
- Python代码:
from binascii import hexlify, unhexlify unhexlify("c8") # b'\xc8' bytes.fromhex('c8') # b'\xc8'
解决方法
问题出在String.fromCharCode的使用上:它会将字节值当作Unicode字符编码来转换,而我们需要的是原始的二进制字节数据。正确的做法是直接使用Uint8Array来存储每个字节的数值,避免字符编码转换带来的失真。
修改后的JavaScript函数:
function hexToBytes(str) { const bytes = new Uint8Array(str.length / 2); for (let i = 0; i < str.length; i += 2) { bytes[i / 2] = parseInt(str.substr(i, 2), 16); } return bytes; }
使用这个函数还原字节后,就可以直接用来创建Blob并生成文件:
const hexStr = "你的十六进制字符串"; const byteArray = hexToBytes(hexStr); const blob = new Blob([byteArray], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }); // 后续可通过URL.createObjectURL(blob)下载文件
原理说明
Uint8Array是JavaScript的类型化数组,专门用于存储8位无符号整数(0-255),正好对应二进制文件的每个字节值,不会进行任何字符编码转换,能精准还原原始字节。- 原函数用
String.fromCharCode会把字节值映射到Unicode字符集中的对应字符,对于大于127的字节值(如0xc8=200),会被当作Latin-1或UTF-16编码的字符,导致原始字节值丢失,最终文件损坏。
内容的提问来源于stack exchange,提问作者Avatar36
相关产品推荐
相关产品推荐

