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 = $('<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(); } } });
后端核心代码
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 '<script>'; echo 'document.addEventListener("DOMContentLoaded", function() {'; echo 'alert("' . $message . '");'; // Display message echo '$(".chk_id:checked").prop("checked", false);'; // Deselect checkboxes echo '});'; echo '</script>'; } } } 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
相关产品推荐
相关产品推荐

