使用JS Blob下载文件提示损坏无法打开,如何排查解决?
问题原因
- 前端请求二进制文件时未指定响应类型,默认拿到的是UTF-8编码的文本字符串,原始二进制字节已被编码破坏
- 对二进制响应使用
JSON.stringify()操作,会进一步将原始字节转换为JSON转义字符串,彻底损坏文件结构 - PHP端未透传上游接口的响应头,返回内容被默认标记为
text/html类型,也会导致前端识别异常
修复方案
前端部分
发送请求时明确指定响应类型为blob或arraybuffer,禁止对二进制响应使用JSON.stringify():
fetch 示例
fetch('/你的PHP接口地址', { // 按需补充请求头、请求方法等配置 }) // 直接读取为blob格式 .then(res => res.blob()) .then(blob => { const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = data.data.name; a.style.display = 'none'; document.body.appendChild(a); a.click(); // 释放内存避免泄漏 URL.revokeObjectURL(a.href); document.body.removeChild(a); })
XMLHttpRequest 示例
const xhr = new XMLHttpRequest(); xhr.open('GET', '/你的PHP接口地址'); // 关键配置:指定响应类型为blob xhr.responseType = 'blob'; xhr.onload = () => { if (xhr.status === 200) { const a = document.createElement('a'); a.href = URL.createObjectURL(xhr.response); a.download = data.data.name; a.click(); URL.revokeObjectURL(a.href); } }; xhr.send();
无需手动指定Blob的type参数,只要上游返回的Content-Type正确,浏览器会自动识别,且下载后的文件通过后缀名也可被系统正常识别,无需提前知道文件类型
PHP部分
透传上游接口的响应头,避免默认text/html类型破坏二进制内容:
$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://myapi.com/webapp/api/v1/document/id/" . $id . "/download"); curl_setopt($ch, CURLOPT_HTTPHEADER, array('AuthenticationToken:' . $token)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); // 获取上游返回的Content-Type $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE); $contentLength = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD); curl_close($ch); // 输出正确响应头 header('Content-Type: ' . $contentType); header('Content-Length: ' . $contentLength); echo $output; exit;
修复后重新下载的文件,执行file test.jpeg会返回正确的文件类型标识,可正常打开。
内容的提问来源于stack exchange,提问作者Desory
相关产品推荐
相关产品推荐

