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

AJAX调用后Modal无法显示TCPDF生成的PDF链接(仅线上异常)

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成功回调仅保留追加操作

既然问题只出现在特定客户+大文件的场景,咱们不用纠结通用逻辑(毕竟本地和其他客户都正常),重点排查以下几个方向:

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:00:15