AJAX调用后Modal无法显示TCPDF生成的PDF链接(仅线上异常)
Troubleshooting: Empty PDF Link Returned for Specific Client on 700+ Page TCPDF Generation
Problem Description
我碰到了一个非常棘手的场景:本地环境测试完全正常,但在生产服务器上,只有一位特定客户在生成700多页的PDF文件时出现异常。通过AJAX调用TCPDF生成PDF后,服务器返回的文件链接是空字符串,导致Modal中生成的链接变成了www.mysite.com/files/customer_name/,而非预期带完整文件名的链接。
Relevant Code
AJAX Frontend Code
$('#stampa-file').on('submit', function(event) { event.preventDefault(); $.ajax({ url:'stampa_file.php?act=stampa', method: 'POST', data: $('#stampa-file').serialize(), success: function(data) { if($.trim(data) == 'query_error') { alert('Qualcosa è andato storto. Riprova.'); } else if($.trim(data) == 'stampa_error') { alert('Seleziona almeno una sezione'); } else { $('#stampa-file')[0].reset(); $('#loadingModal').modal('hide'); $('#document-link').empty(); $('#document-link-download').empty(); $('#document-link').append('<a href="files/<?php echo $_COOKIE['NomeDB'];?>/'+ data +'" class="btn btn-sm btn-success" target="_blank" style="width: 120px;"><i class="fas fa-eye"></i> Visualizza PDF</a>'); $('#document-link-download').append('<a href="files/<?php echo $_COOKIE['NomeDB'];?>/'+ data +'" class="btn btn-sm btn-success" target="_blank" style="width: 120px;" download><i class="fas fa-download"></i> Scarica PDF</a>'); $('#viewFile').modal('show'); } } }); });
TCPDF & Backend Logic (PHP)
//I generate the PDF above this comment. Below only the link generation, PDF output and save the file into the database. //Close and output PDF document $replace = array(" ", "'"); $replacer = array(""); $nome = strtolower($query_ente['nome']); $now = date("Y_m_d_H_i_s", time()); $link = trim(str_replace($replace, $replacer, 'RDAT_'.$nome.'_'.$now.'.pdf')); ob_clean(); $pdf -> Output($path_stampa_file.$link,'F'); $output = ''; $timestamp = time(); $result_inserimento = mysqli_query($mysqli, "INSERT INTO files (link, nome, timestamp, categoria) VALUES ('$link', '$link', '$timestamp', 'stampa_rdt')"); if($result_inserimento) { /*Registro Attività*/ include 'connessione_multi.php'; session_start(); $user_check = $_SESSION['login_user']; $result_user_info = mysqli_query($conn, "SELECT * FROM sessioni_login WHERE session_id='$user_check'"); $query_user_info = mysqli_fetch_assoc($result_user_info); $session_user_id = $query_user_info['id_utente']; $id_utente = $session_user_id; $descrizione = 'ha eseguito la stampa del file: '.$link.''; $timestamp = time(); $indirizzo_ip = $_SERVER['REMOTE_ADDR']; $result_attivita = mysqli_query($mysqli, "INSERT INTO attivita (id_utente, descrizione, timestamp, indirizzo_ip) VALUES ('$id_utente', '$descrizione', '$timestamp', '$indirizzo_ip')"); $output = $link; } else { $output = 'query_error'; } echo $output;
Solutions Already Attempted
- 在AJAX成功回调中发起二次请求从数据库获取链接
- 在AJAX的
complete事件中追加链接 - 在TCPDF生成文件后直接从数据库读取链接
- 简化AJAX成功回调仅保留追加操作
My Analysis & Recommended Fixes
既然问题只出现在特定客户+大文件的场景,咱们不用纠结通用逻辑(毕竟本地和其他客户都正常),重点排查以下几个方向:
1. Check Server Resource Limits for Large PDFs
生成700页的PDF需要大量内存和执行时间,生产服务器的默认PHP配置可能扛不住:
- 在
stampa_file.php开头临时调高资源限制(后续可以在php.ini里永久调整):ini_set('memory_limit', '256M'); // 按需调整,比如512M ini_set('max_execution_time', 300); // 延长到5分钟,避免超时 - 检查
$path_stampa_file对应的目录:- 磁盘空间是否充足?会不会该客户的存储目录已满?
- 目录的写入权限是否正确?确保Web服务器用户(比如www-data)有写入权限。
2. Add Error Handling for TCPDF Output
当前代码没有检查TCPDF的Output()方法是否成功,这个方法写入失败会返回false,但你直接跳过了判断。修改代码捕获这个错误:
ob_clean(); $saveSuccess = $pdf->Output($path_stampa_file.$link, 'F'); if (!$saveSuccess) { $output = 'stampa_error'; error_log("Failed to save PDF: {$path_stampa_file}{$link}"); // 写入错误日志 } else { // 继续数据库插入等后续操作 }
同时查看服务器的PHP错误日志,里面大概率会有内存溢出、权限不足等关键线索。
3. Investigate the Client's Data特殊性
这个客户的数据可能有特殊情况导致PDF生成失败:
- 检查
$query_ente['nome']是否包含特殊字符(比如非ASCII字符、斜杠、超长字符串)?虽然你做了空格和单引号的替换,但可能漏了其他字符,导致文件名无效,无法保存。 - 检查该客户的数据源是否有超长字段、格式错误的内容,导致TCPDF在渲染时崩溃(但没有抛出明显错误)。
4. Fix AJAX Timeout Issue
大文件生成耗时久,AJAX可能提前超时中断请求,导致服务器还没处理完就返回空数据。给AJAX加上超时设置:
$.ajax({ url:'stampa_file.php?act=stampa', method: 'POST', data: $('#stampa-file').serialize(), timeout: 300000, // 5分钟超时时间,按需调整 // ... 其他原有代码 });
5. Debug Database Insertion
虽然你判断了$result_inserimento,但可以进一步排查插入失败的原因:
$result_inserimento = mysqli_query($mysqli, "INSERT INTO files (link, nome, timestamp, categoria) VALUES ('$link', '$link', '$timestamp', 'stampa_rdt')"); if($result_inserimento) { // ... 原有代码 } else { error_log("Database Insert Error: " . mysqli_error($mysqli)); // 记录具体错误 $output = 'query_error'; }
比如files表的link字段长度是否足够?如果$nome特别长,拼接后的$link可能超过字段的最大长度,导致插入失败。
6. Ensure Clean Output Buffer
你用了ob_clean(),但确保在echo之前没有其他隐性输出。可以在echo前加上:
ob_end_clean(); // 彻底清空输出缓冲区 echo $output;
内容的提问来源于stack exchange,提问作者DoomWZ
相关产品推荐
相关产品推荐

