AJAX函数执行停滞:base64解码文件写入file_put_contents遇阻
WordPress AJAX PDF保存&邮件发送超时问题排查与修复
问题场景
开发自定义WordPress插件时,通过jsPDF生成PDF并转为base64字符串,通过AJAX传给PHP函数,本地环境能正常保存文件并发送邮件(仅速度慢),但部署到测试服务器后进程直接停滞超时,无报错且未进入邮件发送环节。核心代码如下:
public function calculator_send_email() { if ( !wp_verify_nonce( $_POST['nonce'], 'calc-nonce' ) ) { wp_die( 'AJAX nonce was not accepted' ); } $to = $_POST['email']; // decode the PDF content and save it as a .pdf file $attachment = base64_decode($_POST['attachment']); $file = WP_CONTENT_DIR . '/uploads/milkpay-' . time() . '.pdf'; file_put_contents( $file, $attachment ); $mail = wp_mail($to, 'Milkpay Results', 'Here are your requested results', [$file]); if ( $file && $mail ) { @unlink( $file ); } echo $mail; wp_die(); }
核心问题分析
- PHP配置限制:base64编码后的PDF体积比原文件大30%,若服务器
post_max_size、memory_limit过小,会导致POST数据截断或解码时内存不足,进程卡住。 - 路径与权限错误:直接用
WP_CONTENT_DIR拼接路径可能导致权限问题,或服务器上传目录路径与本地不一致;uploads目录权限不足会导致file_put_contents写入失败,无报错但进程停滞。 - base64字符串脏数据:前端传输的base64可能包含空格、换行或被URL转义(如
+变为空格),导致解码失败。 - wp_mail参数错误:原代码把附件数组传给了
wp_mail的第四个参数(headers位),而非第五个参数(attachments位),会导致邮件逻辑异常。
修复步骤
1. 修正wp_mail参数错误
这是代码的明显错误,调整邮件调用的参数顺序:
// 正确参数顺序:to, subject, message, headers, attachments $mail = wp_mail($to, 'Milkpay Results', 'Here are your requested results', '', [$file]);
若需指定邮件头,可补充第四个参数:
$headers = array('Content-Type: text/plain; charset=UTF-8'); $mail = wp_mail($to, 'Milkpay Results', 'Here are your requested results', $headers, [$file]);
2. 调整PHP配置参数
联系服务器管理员修改php.ini,或通过.htaccess(Apache)/user.ini(Nginx)临时调整:
post_max_size = 20M:确保能接收大体积base64字符串memory_limit = 128M:给base64解码足够内存max_execution_time = 60:延长执行时间避免超时upload_max_filesize = 20M:与post_max_size保持一致
3. 使用WordPress标准上传路径
替换硬编码路径,用wp_upload_dir()获取正确目录(自动处理权限和路径差异):
$upload_dir = wp_upload_dir(); // 生成唯一文件名避免冲突 $file_name = 'milkpay-' . wp_generate_uuid4() . '.pdf'; $file = $upload_dir['path'] . '/' . $file_name;
4. 清理并验证base64字符串
前后端同时处理,确保传输纯净base64:
- 前端:
// 去除多余空格,仅传递base64部分 const pdfBase64 = doc.output('datauristring').split('base64,')[1].trim();
- 后端:
$attachment_raw = $_POST['attachment']; // 替换URL转义后的空格为+(base64中+被URL编码为空格) $attachment_raw = str_replace(' ', '+', $attachment_raw); // 验证base64有效性,无效则直接返回错误 if (!base64_decode($attachment_raw, true)) { wp_die('Invalid PDF content received'); } $attachment = base64_decode($attachment_raw);
5. 增加错误捕获与日志
开启WordPress调试日志定位错误,在wp-config.php中添加:
define('WP_DEBUG', true); define('WP_DEBUG_LOG', true); define('WP_DEBUG_DISPLAY', false);
同时在代码中增加文件写入错误检查:
$write_result = file_put_contents($file, $attachment); if ($write_result === false) { error_log('Failed to write PDF file to: ' . $file); wp_die('Failed to generate PDF file'); }
6. 优化文件清理逻辑
原判断逻辑存在漏洞,改为:
if (file_exists($file) && $mail) { unlink($file); }
去掉@符号,让错误能被日志捕获。
内容的提问来源于stack exchange,提问作者KreigD
相关产品推荐
相关产品推荐

