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

WordPress插件CSV下载后成功消息不显示问题求助

WordPress插件CSV下载后无法触发成功提示的解决方案

问题描述

我正在开发一款WordPress简易插件,已创建后台页面展示插件自定义MySQL表中的数据。页面中的下载按钮会触发class_myplugin.php文件里的download_csv()函数,CSV文件下载功能正常,但无法触发预设的成功消息(该消息包含取消选中行的脚本及下载完成提示)。

前端提交代码

$('#export_records').on('click', function(e) { 
        var row_data = [];  
        $(".chk_id:checked").each(function() {  
            row_data.push($(this).data('form-id'));
        }); 
        if(row_data.length <=0)  {  
            alert("Please select records.");  
        }  
        else {  
            WRN_PROFILE_DELETE = "Are you sure you want to delete "+(row_data.length>1?"these":"this")+" row?";  
            var confirmed = confirm(WRN_PROFILE_DELETE);  
            if(confirmed == true) {     
            // Create a hidden form and append the selected IDs
            var form = $('&lt;form action="" method="post"&gt;&lt;/form&gt;');
            form.append('&lt;input type="hidden" name="download_csv" value="1"&gt;');
            form.append('&lt;input type="hidden" name="download_csv_nonce" value="&lt;?php echo wp_create_nonce('download_csv_nonce'); ?&gt;"&gt;');
            form.append('&lt;input type="hidden" name="selected_ids" value="' + JSON.stringify(row_data) + '"&gt;');
            form.appendTo('body').submit();
            }
        }
    });

后端核心代码

public function __construct( $plugin_name, $version ) {

        $this->plugin_name = $plugin_name;
        $this->version = $version;
        add_action('admin_menu', array( $this, 'addPluginAdminMenu' ), 9);
        add_action('admin_init', array( $this, 'registerAndBuildFields' )); 
        add_action('admin_notices', array( $this,'sigh_form_tethys_admin_notice'));
        add_action('rest_api_init',array( $this,'sigh_form_handle_delete_entries' ));
        add_action('admin_init', array( $this, 'handle_download_csv' ));
    }
public function handle_download_csv() { 
    if (isset($_POST['download_csv'])) {
        
        if (!isset($_POST['download_csv_nonce']) || !wp_verify_nonce($_POST['download_csv_nonce'], 'download_csv_nonce')) {
            print 'Sorry, your nonce did not verify.';
            exit;
        } else {
            
           // Download CSV
            $success = $this->download_csv($_POST['selected_ids']);
            // Prepare message
            $message = $success ? count($_POST['selected_ids']) . ' records were downloaded.' : 'Failed to download records.';
            // Echo message
            echo '&lt;script&gt;';
            echo 'document.addEventListener("DOMContentLoaded", function() {';
            echo 'alert("' . $message . '");'; // Display message
            echo '$(".chk_id:checked").prop("checked", false);'; // Deselect checkboxes
            echo '});';
            echo '&lt;/script&gt;';
            
        }

    }
}
public function download_csv($selected_ids) {
        // Set headers for CSV file download
        header("Pragma: public");
        header("Expires: 0");
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Cache-Control: private", false);
        header('Content-Type: text/csv; charset=utf-8');
        header("Content-Disposition: attachment; filename=\"csv_export.csv\";" );
        header("Content-Transfer-Encoding: binary");
        // clean output buffer

        // Create a file pointer connected to the output stream
        $output = fopen('php://output', 'w');   
        // Retrieve data from your specific table
        global $wpdb;
        $table_name = $wpdb->prefix . 'sight_form_data'; // Replace 'your_table_name' with the name of your table
        $selected_ids = json_decode($selected_ids);
        $placeholders = implode(',', array_fill(0, count($selected_ids), '%d'));
        $request = $wpdb->prepare("SELECT * FROM $table_name WHERE id_form IN ($placeholders)", $selected_ids);
            $entries = $wpdb->get_results($request, ARRAY_A);
    
                // Write headers to the CSV file
                $header_row = array(
                    'First name', 'Last name', 'Country', 'Email', 'Phone', 'Date sighting', 'Time sighting',
                    'Species', 'Confidence', 'Latitude', 'Longitude', 'N animals', 'Offsprings', 'Sea state',
                    'Want to be contacted', 'Privacy consent', 'Video url', 'File URL'
                );
    
            fputcsv($output, $header_row);
    
            // Write data rows to the CSV file
                foreach ($entries as $entry) {
                    // Prepare an array with values to write to CSV
                    $csv_data = array(
                        $entry['first_name'],
                        $entry['last_name'],
                        $entry['country'],
                        $entry['email'],
                        $entry['phone'],
                        $entry['date_sighting'],
                        $entry['time_sighting'],
                        $entry['species'],
                        $entry['confidence'],
                        $entry['latitude'],
                        $entry['longitude'],
                        $entry['n_animals'],
                        $entry['offsprings'],
                        $entry['sea_state'],
                        $entry['contact'],
                        $entry['consent_privacy'],
                        $entry['video_url'],
                        $entry['fileUrl'] // Assuming this is the field with file URLs
                    );
                    fputcsv($output, $csv_data);
                }
            // Close the file pointer
            fclose($output);
        // flush buffer

        // Terminate script execution
        exit();
}

核心原因

当触发CSV下载时,后端输出了文件下载的HTTP头,浏览器会将整个响应视为文件内容,不会解析后续输出的JS脚本。同时download_csv函数末尾的exit()会直接终止脚本,导致后续的JS代码根本不会被执行。

解决方案

方案1:使用WordPress临时选项+页面重定向(无AJAX)

这种方案利用WordPress的admin_notices钩子和临时选项传递消息,页面重定向后显示通知,同时前端提前取消选中状态。

1. 修改handle_download_csv函数

public function handle_download_csv() { 
    if (isset($_POST['download_csv'])) {
        
        if (!isset($_POST['download_csv_nonce']) || !wp_verify_nonce($_POST['download_csv_nonce'], 'download_csv_nonce')) {
            wp_die('Sorry, your nonce did not verify.');
        } else {
            $selected_ids = $_POST['selected_ids'];
            // 执行CSV下载
            $success = $this->download_csv($selected_ids);
            // 计算选中记录数
            $record_count = count(json_decode($selected_ids));
            // 生成提示消息
            $message = $success ? "$record_count records were downloaded." : 'Failed to download records.';
            // 存储临时消息(10秒过期)
            set_transient('myplugin_download_notice', $message, 10);
            
            // 重定向回原页面,确保通知能显示
            wp_safe_redirect(wp_get_referer());
            exit;
        }
    }
}

2. 修改download_csv函数

移除末尾的exit(),并返回操作状态:

public function download_csv($selected_ids) {
    // 设置CSV下载头
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private", false);
    header('Content-Type: text/csv; charset=utf-8');
    header("Content-Disposition: attachment; filename=\"csv_export.csv\";" );
    header("Content-Transfer-Encoding: binary");
    
    ob_clean(); // 清理输出缓冲区,避免乱码
    flush();

    // 创建输出流指针
    $output = fopen('php://output', 'w');   
    global $wpdb;
    $table_name = $wpdb->prefix . 'sight_form_data';
    $selected_ids = json_decode($selected_ids);
    $placeholders = implode(',', array_fill(0, count($selected_ids), '%d'));
    $request = $wpdb->prepare("SELECT * FROM $table_name WHERE id_form IN ($placeholders)", $selected_ids);
    $entries = $wpdb->get_results($request, ARRAY_A);

    // 无数据则返回失败
    if(empty($entries)){
        fclose($output);
        return false;
    }

    // 写入CSV表头
    $header_row = array(
        'First name', 'Last name', 'Country', 'Email', 'Phone', 'Date sighting', 'Time sighting',
        'Species', 'Confidence', 'Latitude', 'Longitude', 'N animals', 'Offsprings', 'Sea state',
        'Want to be contacted', 'Privacy consent', 'Video url', 'File URL'
    );
    fputcsv($output, $header_row);

    // 写入数据行
    foreach ($entries as $entry) {
        $csv_data = array(
            $entry['first_name'],
            $entry['last_name'],
            $entry['country'],
            $entry['email'],
            $entry['phone'],
            $entry['date_sighting'],
            $entry['time_sighting'],
            $entry['species'],
            $entry['confidence'],
            $entry['latitude'],
            $entry['longitude'],
            $entry['n_animals'],
            $entry['offsprings'],
            $entry['sea_state'],
            $entry['contact'],
            $entry['consent_privacy'],
            $entry['video_url'],
            $entry['fileUrl']
        );
        fputcsv($output, $csv_data);
    }
    fclose($output);
    flush();
    return true;
}

3. 更新admin_notices钩子函数

添加临时消息的显示逻辑:

public function sigh_form_tethys_admin_notice() {
    // 获取临时消息
    $notice = get_transient('myplugin_download_notice');
    if ($notice) {
        echo '<div class="notice notice-success is-dismissible">';
        echo '<p>' . esc_html($notice) . '</p>';
        echo '</div>';
        // 显示后删除临时消息
        delete_transient('myplugin_download_notice');
    }
    // 保留原有通知逻辑...
}

4. 前端提前取消选中状态

修改JS,在提交表单前取消选中:

$('#export_records').on('click', function(e) { 
    var row_data = [];  
    $(".chk_id:checked").each(function() {  
        row_data.push($(this).data('form-id'));
    }); 
    if(row_data.length <=0)  {  
        alert("Please select records.");  
    }  
    else {  
        var WRN_PROFILE_DELETE = "Are you sure you want to export "+(row_data.length>1?"these":"this")+" row?";  
        var confirmed = confirm(WRN_PROFILE_DELETE);  
        if(confirmed == true) {     
            // 提交前取消选中
            $(".chk_id:checked").prop("checked", false);
            // 创建隐藏表单并提交
            var form = $('<form action="" method="post"></form>');
            form.append('<input type="hidden" name="download_csv" value="1">');
            form.append('<input type="hidden" name="download_csv_nonce" value="<?php echo wp_create_nonce('download_csv_nonce'); ?>">');
            form.append('<input type="hidden" name="selected_ids" value="' + JSON.stringify(row_data) + '">');
            form.appendTo('body').submit();
        }
    }
});

方案2:使用AJAX触发下载(无页面刷新)

这种方案通过AJAX获取CSV内容,前端创建下载链接,同时直接显示提示并取消选中状态。

1. 修改前端JS代码

$('#export_records').on('click', function(e) { 
    e.preventDefault();
    var row_data = [];  
    $(".chk_id:checked").each(function() {  
        row_data.push($(this).data('form-id'));
    }); 
    if(row_data.length <=0)  {  
        alert("Please select records.");  
        return;
    }  
    var WRN_PROFILE_DELETE = "Are you sure you want to export "+(row_data.length>1?"these":"this")+" row?";  
    var confirmed = confirm(WRN_PROFILE_DELETE);  
    if(confirmed == true) {     
        $.ajax({
            url: ajaxurl, // WordPress内置AJAX地址
            type: 'POST',
            data: {
                action: 'myplugin_download_csv',
                download_csv_nonce: '<?php echo wp_create_nonce('download_csv_nonce'); ?>',
                selected_ids: JSON.stringify(row_data)
            },
            success: function(response) {
                if(response.success){
                    // 创建CSV下载链接
                    var blob = new Blob([response.data.csv], {type: 'text/csv;charset=utf-8;'});
                    var url = URL.createObjectURL(blob);
                    var link = document.createElement('a');
                    link.href = url;
                    link.setAttribute('download', 'csv_export.csv');
                    document.body.appendChild(link);
                    link.click();
                    document.body.removeChild(link);
                    // 显示提示并取消选中
                    alert(response.data.message);
                    $(".chk_id:checked").prop("checked", false);
                } else {
                    alert(response.data.message);
                }
            },
            error: function() {
                alert('Failed to download records.');
            }
        });
    }
});

2. 后端添加AJAX钩子和处理函数

在构造函数中注册AJAX动作:

add_action('wp_ajax_myplugin_download_csv', array( $this, 'ajax_download_csv' ));

添加AJAX处理函数:

public function ajax_download_csv() {
    // 验证nonce
    check_ajax_referer('download_csv_nonce', 'download_csv_nonce');
    $selected_ids = $_POST['selected_ids'];
    $selected_ids_arr = json_decode($selected_ids);
    
    global $wpdb;
    $table_name = $wpdb->prefix . 'sight_form_data';
    $placeholders = implode(',', array_fill(0, count($selected_ids_arr), '%d'));
    $request = $wpdb->prepare("SELECT * FROM $table_name WHERE id_form IN ($placeholders)", $selected_ids_arr);
    $entries = $wpdb->get_results($request, ARRAY_A);

    // 无数据返回错误
    if(empty($entries)){
        wp_send_json_error(array('message' => 'Failed to download records.'));
    }

    // 生成CSV内容
    ob_start();
    $output = fopen('php://output', 'w');
    $header_row = array(
        'First name', 'Last name', 'Country', 'Email', 'Phone', 'Date sighting', 'Time sighting',
        'Species', 'Confidence', 'Latitude', 'Longitude', 'N animals', 'Offsprings', 'Sea state',
        'Want to be contacted', 'Privacy consent', 'Video url', 'File URL'
    );
    fputcsv($output, $header_row);
    foreach ($entries as $entry) {
        $csv_data = array(
            $entry['first_name'],
            $entry['last_name'],
            $entry['country'],
            $entry['email'],
            $entry['phone'],
            $entry['date_sighting'],
            $entry['time_sighting'],
            $entry['species'],
            $entry['confidence'],
            $entry['latitude'],
            $entry['longitude'],
            $entry['n_animals'],
            $entry['offsprings'],
            $entry['sea_state'],
            $entry['contact'],
            $entry['consent_privacy'],
            $entry['video_url'],
            $entry['fileUrl']
        );
        fputcsv($output, $csv_data);
    }
    fclose($output);
    $csv_content = ob_get_clean();

    // 返回成功响应
    wp_send_json_success(array(
        'csv' => $csv_content,
        'message' => count($selected_ids_arr) . ' records were downloaded.'
    ));
}

内容的提问来源于stack exchange,提问作者Elena Politi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 20:14:52