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

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('未收到图片数据');
}

额外注意事项

  1. 确保$tempFolder指向的目录存在且PHP有写入权限,否则无法生成临时图片文件。
  2. 可以先手动打开生成的临时图片文件,如果能正常打开,说明解码和写入没问题,问题就出在邮件发送环节;如果打不开,就是解码步骤出错。
  3. 发送邮件后可以删除临时文件,避免磁盘空间浪费。

内容的提问来源于stack exchange,提问作者Juliette Fontaine

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 20:35:55