含特殊字符文件的GitHub REST API SHA校验异常问题求助
解决含特殊字符文件SHA校验不一致的问题
问题背景
当前代码依赖二次校验areReallyEqual才能正确判断含特殊字符(如ñ、é、à)的文件是否与远程仓库文件一致,无特殊字符的文件则无需此逻辑。核心问题出在SHA值的计算逻辑不符合GitHub的规则。
问题根源
GitHub计算文件SHA的规则是基于blob <字节长度>\x00<文件内容>的二进制数据生成SHA1,其中字节长度是文件内容以UTF-8编码后的实际字节数。但现有GitHubCrypto.getSha方法中,fileContent.length获取的是字符串的字符数——对于UTF-8中占多字节的特殊字符(比如ñ占2字节、é占2字节),字符数≠字节数,导致构建的blob格式错误,最终生成的SHA与GitHub返回的repositoryFile.sha不匹配。
解决方案:修正SHA计算逻辑
修改GitHubCrypto.getSha方法,正确计算UTF-8字节长度,并按照GitHub的二进制规则生成SHA:
class GitHubCrypto { /** * @param {string} fileContent * @returns {string} SHA1 hash string */ static getSha(fileContent) { // 将字符串编码为UTF-8字节数组,获取真实字节长度 const encoder = new TextEncoder(); const contentBytes = encoder.encode(fileContent); const byteLength = contentBytes.length; // 构建GitHub要求的blob前缀:"blob <字节长度>\x00" const prefixStr = `blob ${byteLength}\x00`; const prefixBytes = encoder.encode(prefixStr); // 合并前缀和内容字节数组,得到完整的blob二进制数据 const blobData = new Uint8Array(prefixBytes.length + contentBytes.length); blobData.set(prefixBytes); blobData.set(contentBytes, prefixBytes.length); // 针对二进制数据计算SHA1 // 注意:如果你的Sha1.hash仅支持字符串输入,替换为以下两行: // const blobStr = String.fromCharCode(...blobData); // const sha = Sha1.hash(blobStr); const sha = Sha1.hash(blobData); return sha; } }
额外验证点
- 确保
Sha1.hash方法支持处理Uint8Array类型的二进制数据,如果原实现仅支持字符串,使用String.fromCharCode(...blobData)将字节数组转换为二进制字符串后传入。 - 确认
getScriptInternalFiles中获取的文件内容是UTF-8编码(当前已设置Accept-Charset: utf-8,无需调整)。 - 远程文件下载逻辑
fetchGitHubGetUrl需保证返回的是原始UTF-8字节内容,避免编码转换导致字节不一致。
修改完成后,直接对比internalFileTextSha与repositoryFile.sha即可,无需二次校验,特殊字符文件的SHA计算将与GitHub完全一致。
内容的提问来源于stack exchange,提问作者Xavier Peña
相关产品推荐
相关产品推荐

