使用Azure Blob Storage的PUT Block接口上传Zip文件后出现格式不支持问题
我看了你的代码,发现几个关键问题导致上传后的Zip文件损坏,最核心的是二进制数据处理错误,另外还有几个小问题需要修正:
1. 核心问题:字符串拼接破坏二进制数据
你现在用blobContent = blobContent + chunk来累积文件块,但chunk是Buffer类型,和字符串拼接时会自动把Buffer转成UTF-8字符串。Zip文件是纯二进制格式,包含很多无法用UTF-8正确编码的字节,这个转换过程会直接篡改或丢失数据,导致下载后的文件完全损坏。
修复方法:用Buffer累积二进制数据
把blobContent改成Buffer类型,用Buffer.concat来拼接块:
// 初始化时改为空Buffer let blobContent = Buffer.alloc(0) // ... readStream.on('data', function (chunk) { // 用Buffer.concat拼接二进制块 blobContent = Buffer.concat([blobContent, chunk]) contentLength = blobContent.length if (contentLength >= thresholdSize) { console.log('content length is:', contentLength) putBlock(blobContent, contentLength) contentLength = 0 blobContent = Buffer.alloc(0) } })
2. Put Block List请求的Content-Type错误
你当前给Put Block List请求设置的Content-Type是application/text-plain,但根据Azure的要求,这个请求的Content-Type必须是application/xml,否则服务端可能无法正确解析XML格式的块列表(虽然可能返回201,但实际块的组装可能有问题)。
修复方法:修正Content-Type
// 在putBlockList函数的optionsPutBlockList.headers中修改 'Content-Type': 'application/xml'
3. 建议设置Blob的Content-Type
虽然PUT Block接口不要求Content-Type,但在Put Block List请求中添加x-ms-blob-content-type头,把Blob的MIME类型设为application/zip,这样下载后系统能正确识别文件类型,避免不必要的格式报错:
// 在optionsPutBlockList的headers里添加 'x-ms-blob-content-type': 'application/zip'
4. 统一时间戳的潜在问题
你现在的strTime是初始化时生成的,如果上传大文件耗时较长,这个时间可能超出请求的有效时间范围(Azure对请求时间有一定的容忍度,但最好规范处理)。建议在每个请求函数里生成当前的UTC时间:
// 在putBlock函数内生成当前时间 function putBlock (blobContent, contentLength) { const strTime = new Date().toUTCString() // ... 其他代码 } // 在putBlockList函数内也生成当前时间 function putBlockList () { const strTime = new Date().toUTCString() // ... 其他代码 }
把这些修改完成后,重新上传Zip文件,下载后应该就能正常打开了。核心问题就是字符串处理二进制数据导致的损坏,这是处理二进制文件上传时很容易踩的坑。
内容的提问来源于stack exchange,提问作者Mayank Patel

