Laravel foreach构建PDF内容 生产环境返回空白页问题
生产环境PDF生成空白页问题排查
问题场景
通过存储过程向PDF模板传递数据,使用foreach循环遍历返回的JSON数据构建PDF内部内容项,本地环境运行正常,可生成包含完整内容的PDF文件;部署到远程生产服务器后,生成的PDF为空白页。当前本地与生产环境的控制器代码、模板代码完全一致,存储过程返回的数据内容也完全一致。
控制器PHP代码
public function generarFichaPago(Request $request) { $datosPDF = DB::select('exec SP_GenerarPDF @Op = ?, @matricula = ?, @ciclo = ?, @mes = ?', ['fichaPago', $request->matricula, $request->ciclo, $request->mes]); $pdf = PDF::loadView('Oficios.FichaPagoInsc', compact('datosPDF'))->setPaper('a4'); $path = public_path('pdf/'); $fileName = time().'.'. 'pdf' ; $pdf->save($path . '/' . $fileName); $pdf = public_path('pdf/'.$fileName); return response()->download($pdf); }
前端Ajax调用代码
function generarReferencia(mes) { var ciclo = document.getElementById("ciclo").value; var matricula = document.getElementById("matricula").value; console.log(ciclo,matricula,mes); $.ajax({ type: 'GET', url: '/pdf/fichaPago', data: { "matricula": matricula, "ciclo": ciclo, "mes": mes, }, xhrFields: { responseType: 'blob' }, success: function(response){ var blob = new Blob([response]); var link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); link.download = "Sample.pdf"; link.click(); }, error: function(blob){ console.log(blob); } });
Blade PDF模板代码
<div class="container"> @foreach ($datosPDF as $dato) <div id="n1" class="cell"> {{-- <img src="{{ asset('images/logo_bbva.jpg') }}" width="105" height="105"> --}} Num. CIE: XXXXXXXXXXX </div> <div id="n2" class="cell"> <ul style="list-style-type:none;"> <li>Alumno: <strong>{{$dato->MATRICULA}} {{$dato->NOMBRE_P}}</strong></li> <li>Ciclo Escolar: <strong>{{$dato->CICLO}}</strong></li> <li>Nivel: <strong>{{$dato->SECCION}}</strong></li> <li>Grado: <strong>{{$dato->GRADO}}°</strong></li> </ul> <div id="leyenda"> <strong style="color: blue">Pago Inscripción Ciclo {{$dato->CICLO}}</strong> </div> </div> <div id="n3" class="cell"> <br> <ul style="list-style-type:none;"> <li>Referencia: <strong>1234567890</strong></li> <li>Vigencia Al: <strong>{{$dato->FECHA_LIM}}</strong></li> <li>Importe: <strong>{{$dato->IMP_PAG}}</strong></li> </ul> </div> <div id="n4" class="cell"> <p>___________ FIRMA</p> </div> @endforeach </div>
排查方向与修复方案
- 目录权限问题:优先检查生产环境
public/pdf/目录的写入权限,权限不足时会生成空文件,给目录配置可写权限即可:执行chmod -R 755 项目实际路径/public/pdf后重试。 - PHP依赖扩展缺失:确认生产环境PHP安装了PDF生成库必需的
dom、gd、mbstring扩展,缺失任意一个都会导致渲染中断输出空白。执行php -m查看已安装扩展,缺失的扩展安装完成后重启php-fpm服务即可。 - 返回字段名大小写不匹配:本地和生产环境的SQL Server驱动配置可能存在差异,部分驱动默认返回全小写字段名,和模板中写的大写属性(比如
$dato->MATRICULA)不匹配,会导致foreach循环读不到变量、无内容输出。在控制器中把$datosPDF写入日志,确认实际返回的对象属性名,和模板中的写法对齐即可。 - 输出缓冲区污染:如果项目代码在PDF输出前提前输出了BOM头、空行或者报错内容,会破坏PDF文件结构导致打开空白。在调用
PDF::loadView前加一句ob_end_clean()清空所有提前输出的内容,再执行PDF生成逻辑即可。 - 字体/特殊字符兼容问题:生产环境如果没有安装模板用到的字体,或者特殊字符(比如模板中的°符号、西语重音字符)无法被现有字体识别,也会导致内容渲染失败。可以先把模板里的特殊字符替换成普通英文字符测试,能正常生成的话,把对应字体文件放到PDF库的字体目录下加载即可。
- 前端响应接收问题:先跳过Ajax,直接在浏览器访问控制器对应的路由,看能否直接下载正常的PDF。如果直接访问能拿到正常文件,说明是前端Ajax请求的响应被额外内容污染,检查生产环境是否有全局中间件给响应追加了调试内容、或者接口返回的报错信息混入了blob数据。
内容的提问来源于stack exchange,提问作者Claudio César Pérez Velasco
相关产品推荐
相关产品推荐

