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

WordPress更新文章后用TCPDF生成PDF失败求助

问题排查与修复方案

核心问题分析

你的代码在save_post钩子中直接输出PDF,而WordPress在文章保存完成后默认会发送跳转响应(返回编辑页),这会导致PDF的HTTP头被覆盖,浏览器无法接收到正确的PDF内容,因此没有任何反应。此外代码还存在几个细节问题:

  • save_post触发场景未过滤:该钩子会在自动保存、修订版创建时触发,这些场景不需要生成PDF
  • 作者信息错误:$post->post_author返回的是用户ID,不是显示名称
  • 未终止后续流程:输出PDF后未停止WordPress的后续执行,会干扰PDF输出

修复步骤与代码调整

方案一:生成PDF到服务器,后台显示下载链接

避免响应头冲突,先将PDF保存到服务器,再通过后台通知告知用户下载:

require_once(WP_CONTENT_DIR . '/mu-plugins/tcpdf/tcpdf.php'); 

function generate_pdf_from_post($post_id) {
    $post = get_post($post_id);
    if (!$post) return false;

    // 应用内容过滤器,解析短代码与格式
    $content = apply_filters('the_content', $post->post_content);
    // 获取作者显示名称
    $author_name = get_the_author_meta('display_name', $post->post_author);

    // 创建PDF实例
    $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
    $pdf->SetCreator(PDF_CREATOR);
    $pdf->SetAuthor($author_name);
    $pdf->SetTitle($post->post_title);
    $pdf->setPrintHeader(false);
    $pdf->setPrintFooter(false);
    $pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
    $pdf->AddPage();
    $pdf->writeHTML($content, true, false, true, false, '');

    // 保存PDF到uploads目录
    $upload_dir = wp_upload_dir();
    $pdf_filename = sanitize_title($post->post_title) . '-' . time() . '.pdf';
    $pdf_path = $upload_dir['path'] . '/' . $pdf_filename;
    $pdf->Output($pdf_path, 'F');

    return $pdf_path;
}

function generate_pdf_on_save($post_id, $post, $update) {
    // 排除无效触发场景:非更新、自动保存、修订版、非目标自定义类型
    if (!$update || wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) return;
    
    $custom_post_types = array('properties_for_sale', 'vacation_rentals', 'long_term_rentals');
    if (!in_array($post->post_type, $custom_post_types)) return;

    // 生成PDF并添加后台通知
    $pdf_path = generate_pdf_from_post($post_id);
    if ($pdf_path) {
        add_action('admin_notices', function() use ($pdf_path) {
            $download_url = str_replace(ABSPATH, site_url('/'), $pdf_path);
            echo '<div class="notice notice-success is-dismissible">
                    <p>PDF已生成:<a href="' . esc_url($download_url) . '" target="_blank">点击下载</a></p>
                  </div>';
        });
    }
}
add_action('save_post', 'generate_pdf_on_save', 10, 3);

方案二:添加自定义按钮直接生成并下载PDF

如果希望点击按钮直接触发PDF下载,可在文章编辑页添加独立操作按钮:

require_once(WP_CONTENT_DIR . '/mu-plugins/tcpdf/tcpdf.php'); 

// 在编辑页添加自定义按钮
add_action('post_submitbox_misc_actions', 'add_generate_pdf_button');
function add_generate_pdf_button() {
    global $post;
    $custom_post_types = array('properties_for_sale', 'vacation_rentals', 'long_term_rentals');
    if (!in_array($post->post_type, $custom_post_types)) return;

    echo '<div class="misc-pub-section">
            <a href="' . admin_url('admin-post.php?action=generate_post_pdf&post_id=' . $post->ID) . '" class="button button-secondary">生成并下载PDF</a>
          </div>';
}

// 处理按钮请求,输出PDF
add_action('admin_post_generate_post_pdf', 'handle_generate_pdf_request');
function handle_generate_pdf_request() {
    // 权限验证
    if (!current_user_can('edit_post', $_GET['post_id'])) {
        wp_die('无权限操作');
    }

    $post_id = absint($_GET['post_id']);
    $post = get_post($post_id);
    if (!$post) wp_die('文章不存在');

    $content = apply_filters('the_content', $post->post_content);
    $author_name = get_the_author_meta('display_name', $post->post_author);

    $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
    $pdf->SetCreator(PDF_CREATOR);
    $pdf->SetAuthor($author_name);
    $pdf->SetTitle($post->post_title);
    $pdf->setPrintHeader(false);
    $pdf->setPrintFooter(false);
    $pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
    $pdf->AddPage();
    $pdf->writeHTML($content, true, false, true, false, '');

    // 输出PDF到浏览器并终止流程
    $pdf->Output(sanitize_title($post->post_title) . '.pdf', 'I');
    exit();
}

关键修复点说明

  • 过滤save_post的无效触发场景,避免无意义的PDF生成
  • 修正作者名称获取逻辑,显示正确的用户名
  • 方案一通过服务器存储+后台通知的方式,绕开响应头冲突问题
  • 方案二使用独立的admin_post请求处理PDF输出,确保HTTP头正确发送
  • 对文章内容应用the_content过滤,解析短代码和格式,让PDF内容与前台显示一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 11:50:31