Python API传递Base64编码文件,PHP下载后损坏求助
问题分析与解决方案
你的核心问题是通过Base64传递PDF/XLSX文件后,下载的文件损坏,但本地文件正常。以下是具体问题排查和修复方案:
问题根源
- Python端PDF数据未完成写入:早期代码中调用
getpdfdata()前未执行c.save(),导致生成的PDF数据不完整;后续即使保存了文件,直接调用c.getpdfdata()仍可能存在数据未完全刷新的问题。 - PHP端输出缓冲与多余字符:如果
sendAPIRequest返回的内容包含多余字符(如调试日志、空白换行),或输出前未清理缓冲,会导致文件头部混入无效数据,引发损坏。 - 二进制长度计算的潜在风险:虽然
strlen()在PHP中可处理二进制数据,但如果存在编码转换或隐藏字符,仍可能导致Content-Length不准确,破坏文件结构。
修复方案
方案1:Python端改用内存流生成PDF(无需本地文件)
避免本地文件IO,直接在内存中生成完整的PDF数据:
@goals.route('/getPdfB64',methods=['GET']) def getPdfB64(): from io import BytesIO # 用内存流替代本地文件 output = BytesIO() c = canvas.Canvas(output, pagesize=landscape(A4)) c.drawString(300, 300, f'TEST') # 必须调用save()完成PDF写入流程 c.save() # 将流指针移到开头,读取完整二进制数据 output.seek(0) pdf = output.read() pdf_b64 = base64.b64encode(pdf).decode('utf-8') data = { "code" : 200, "value" : { "base64" : pdf_b64 } } return jsonify(data)
方案2:PHP端清理输出并规范响应头
确保输出前无多余内容,严格控制响应头:
<?php // 开启输出缓冲,防止之前的隐性输出破坏文件 ob_start(); $api_response = sendAPIRequest("GET", "localhost:5000/getPdfB64",[]); // 先验证API返回是否为纯JSON(可临时echo $api_response排查) $file_data = json_decode($api_response); if(!$file_data || !isset($file_data->value->base64)){ die("API请求失败或返回格式错误"); } $file = base64_decode($file_data->value->base64); // 清空缓冲,确保没有多余字符输出 ob_clean(); // 设置标准文件传输头 header('Content-Description: File Transfer'); header("Content-Type: application/pdf"); header("Content-Disposition: attachment; filename=Report.pdf"); header("Content-Length: ".strlen($file)); // 禁用缓存避免文件异常 header("Cache-Control: no-cache, no-store, must-revalidate"); header("Pragma: no-cache"); header("Expires: 0"); echo $file; exit; ?>
方案3:排查API请求函数
检查sendAPIRequest函数,确保它只返回纯JSON数据,没有额外的echo、日志打印或HTML内容——这些都会污染Base64字符串,导致解码后文件损坏。
验证步骤
- 直接访问Python API接口,复制返回的
base64字段内容,用在线Base64转文件工具验证是否能正常打开,确认Base64本身无问题。 - 在PHP端
base64_decode后,先将内容保存到本地文件:file_put_contents('test.pdf', $file);,如果本地文件能打开,说明是响应输出环节的问题;如果仍损坏,回到Python端排查数据生成逻辑。
内容的提问来源于stack exchange,提问作者Antharaz
相关产品推荐
相关产品推荐

