JS截图经PHP用PHPMailer发邮件,附件PNG无法打开求助
问题分析与解决:截图附件无法正常打开
问题根源
你的代码里,JS端对canvas生成的base64字符串多做了一次encodeURIComponent()编码,而FormData本身会自动处理传输时的URL编码,这就导致后端PHP拿到的base64字符串被二次转义——比如base64里的+会变成%2B,后续base64解码时无法还原出正确的图片二进制数据,最终生成的文件自然不是有效的PNG。
编码解码相关概念简单说明
canvas.toDataURL():把画布内容转成data:image/png;base64,xxxx格式的字符串,其中xxxx是图片二进制数据经过base64编码后的文本(目的是把二进制转成纯文本,方便在HTTP里传输)。encodeURIComponent():用来把URL里的特殊字符转义成百分号编码(比如+→%2B),但FormData在提交时会自动做这件事,手动加就会导致base64字符串被破坏。base64_decode():把base64文本还原成原始的二进制数据,只有输入的base64字符串完全正确,才能得到有效的图片文件。
修正后的代码
JS代码(去掉多余的编码步骤)
var canvas = document.getElementById('drawCanvas'); async function sendEmail() { var url = '/wp-content/themes/julietcolombe/sendEmail.php'; var drawingData = canvas.toDataURL(); // 去掉encodeURIComponent,直接把原始的dataURL放到FormData里 var formData = new FormData(); formData.append('drawingData', drawingData); fetch(url, { method: 'POST', body: formData }) .then(function (response) { return response.text(); }) .then(function (body) { console.log(body); }); }
PHP代码(调整附件添加方式,确保文件正常)
$drawingData = isset($_POST['drawingData']) ? $_POST['drawingData'] : false; // 先确认$tempFolder已经定义且存在,比如$tempFolder = './temp/';,要确保目录有写权限 $tempFolder = './temp/'; if (!is_dir($tempFolder)) { mkdir($tempFolder, 0777, true); } if ($drawingData) { // 剥离dataURL前缀,得到纯base64字符串 $imageData = base64_decode(str_replace('data:image/png;base64,', '', $drawingData)); $imageName = uniqid() . '.png'; $imagePath = $tempFolder . $imageName; // 写入文件前可以先验证解码是否成功 if ($imageData === false) { die('Base64解码失败'); } file_put_contents($imagePath, $imageData); $mail = new PHPMailer(true); try { $mail->SMTPDebug = 2; $mail->isSMTP(); $mail->Host = "sandbox.smtp.mailtrap.io"; $mail->SMTPAuth = true; $mail->Username = "***"; $mail->Password = "***"; $mail->Port = 25; $mail->From = "***e@gmail.com"; $mail->addAddress("**e@gmail.com"); $mail->isHTML(true); $mail->Subject = 'Screenshot'; $mail->Body = 'New screen by : xx '; // 因为已经把文件写到磁盘了,直接传文件路径即可,不需要指定base64编码 $mail->addAttachment($imagePath, $imageName); $mail->send(); echo '邮件发送成功'; // 可选:发送后删除临时文件 unlink($imagePath); } catch (Exception $e) { echo "邮件发送失败: {$mail->ErrorInfo}"; // 删除损坏的临时文件 if (file_exists($imagePath)) { unlink($imagePath); } } } else { die('未收到图片数据'); }
额外注意事项
- 确保
$tempFolder指向的目录存在且PHP有写入权限,否则无法生成临时图片文件。 - 可以先手动打开生成的临时图片文件,如果能正常打开,说明解码和写入没问题,问题就出在邮件发送环节;如果打不开,就是解码步骤出错。
- 发送邮件后可以删除临时文件,避免磁盘空间浪费。
内容的提问来源于stack exchange,提问作者Juliette Fontaine
相关产品推荐
相关产品推荐

