You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS从Base64字符串生成PPTX文件损坏问题及修复问询

解决PPT文件下载损坏问题

问题背景

此前在AngularJS/PHP项目中,PHP生成PowerPoint文件并下载的功能正常,但改用ReactJS调用同一PHP接口后,生成的PPT文件打开显示损坏。将文件改为.txt查看,内容是一连串单数字(如0753420020807097134859119432551731005080019000916711111011610111011……),而非正确的二进制内容(如PK ‡i„U[Âÿ­ 2  [Content_Types].xmlµUKoÛ0 ¾çWº±Ò†¡ˆÓÃÚžö(Ðö h6í¨Õ……),推测是解码和文件构建过程出错。

原代码

PHP代码

public function generateRiskSummaryPresentation()
{
   //header("Content-Type: application/vnd.openxmlformats-officedocument.presentationml.presentation; charset=utf-8");
   header("charset=utf8");
   //header("Content-Disposition: attachment; filename=RiskSummary.pptx");
   ob_start();
   $oWriterPPTX = IOFactory::createWriter($this->riskPPT,'PowerPoint2007');
   $oWriterPPTX->save("php://output");  
   $presentationContent = ob_get_contents();
   ob_end_clean();  
   return base64_encode($presentationContent);                                      
}

ReactJS代码

getRiskReport = (riskid) => {
    const requestOptions = {
        method: 'GET',
        mode: 'cors',
        headers: {'Content-Type': 'application/json' }
    };        
    return fetch("http://riskaim/api/riskreport/"+riskid, requestOptions)     
    .then(res => res.json())
    .then(result => {
        let content = Buffer.from(result.data, 'base64');
        let file = new Blob([...content], {type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation', charset: 'utf-8'});
        let downloadLink = document.createElement("a");
        downloadLink.setAttribute('style', 'display: none');
        downloadLink.setAttribute('href', window.URL.createObjectURL(file));
        downloadLink.setAttribute('target', '_blank');
        downloadLink.setAttribute('downloadLink', 'RiskSummary.pptx');
        downloadLink.click();
    });
} 

问题分析

  1. PHP端:接口未正确设置响应的Content-Type为application/json,仅设置charset=utf8可能导致base64字符串在JSON序列化时出现编码异常。另外直接返回base64字符串而非标准JSON结构,会导致JS解析出错。
  2. JS端:
    • 浏览器环境不存在Node.js的Buffer对象,直接使用Buffer.from会将base64解码为数字序列,而非正确的二进制数据。
    • 创建Blob时添加了多余的charset参数,PPT是二进制文件,该参数无效且可能干扰文件编码。
    • 下载链接的属性错误,应使用download而非downloadLink。

修正方案

修改后的PHP代码

确保返回标准JSON格式的响应:

public function generateRiskSummaryPresentation()
{
   // 设置正确的JSON响应头
   header("Content-Type: application/json; charset=utf-8");
   ob_start();
   $oWriterPPTX = IOFactory::createWriter($this->riskPPT,'PowerPoint2007');
   $oWriterPPTX->save("php://output");  
   $presentationContent = ob_get_contents();
   ob_end_clean();  
   // 以JSON格式返回base64编码内容
   echo json_encode(['data' => base64_encode($presentationContent)]);
   exit; // 确保后续无额外输出干扰
}

修改后的ReactJS代码

使用浏览器原生API完成base64解码与二进制文件构建:

getRiskReport = (riskid) => {
    const requestOptions = {
        method: 'GET',
        mode: 'cors',
        headers: {'Accept': 'application/json' } // GET请求用Accept指定期望响应格式更合理
    };        
    return fetch("http://riskaim/api/riskreport/"+riskid, requestOptions)     
    .then(res => res.json())
    .then(result => {
        // 解码base64字符串
        const binaryStr = atob(result.data);
        // 将字符串转换为Uint8Array二进制数组
        const uint8Array = new Uint8Array(binaryStr.length);
        for (let i = 0; i < binaryStr.length; i++) {
            uint8Array[i] = binaryStr.charCodeAt(i);
        }
        // 创建二进制Blob,无需charset参数
        const file = new Blob([uint8Array], {type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation'});
        const downloadLink = document.createElement("a");
        downloadLink.style.display = 'none';
        downloadLink.href = window.URL.createObjectURL(file);
        downloadLink.download = 'RiskSummary.pptx'; // 正确设置下载文件名
        document.body.appendChild(downloadLink); // 添加到DOM确保兼容性
        downloadLink.click();
        // 清理资源,避免内存泄漏
        window.URL.revokeObjectURL(downloadLink.href);
        document.body.removeChild(downloadLink);
    });
} 

关键说明

  • PHP端必须通过echo json_encode(...)返回标准JSON结构,不能直接返回base64字符串,否则JS无法正确解析。
  • 浏览器中解码base64需用原生atob()方法,再转换为Uint8Array才能正确构建二进制Blob。
  • 下载链接需临时添加到DOM中,避免部分浏览器兼容性问题,使用后记得清理URL对象和DOM元素。

内容的提问来源于stack exchange,提问作者Vahe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 03:15:40