如何使用PHPMailer库将下载的Excel文件作为邮件附件发送
问题根因
- 你当前代码仅将Excel内容直接输出到浏览器触发下载,没有实际生成文件到你填写的附件路径
/home/winningcodie/Downloads/INTRANSIT_Report.xls,PHPMailer加载不存在的附件时抛出未捕获错误,触发网站500报错表现为无法访问。 - 你在输出下载内容后额外输出邮件发送结果,会导致下载的Excel文件末尾被追加多余内容,文件损坏无法正常打开。
- 代码中的
sleep(5)没有实际作用:服务器端的休眠不会等待客户端完成下载,只会拉长请求响应时间增加超时概率。 - 你填写的附件路径权限存在问题:
/home/用户/Downloads是个人用户私有目录,PHP运行的web服务进程(通常是www-data、apache等)没有访问权限,就算有文件也读取不到。
修复方案
- 先生成Excel内容写入服务器本地可访问的临时文件,确保PHP进程对存储目录有读写权限
- 调用PHPMailer加载该本地文件作为附件发送邮件
- 发送完成后再将文件内容输出到浏览器触发下载,可选删除服务器端临时文件避免占用空间
修正后代码
<?php require("PHPMailer/src/SMTP.php"); require("PHPMailer/src/PHPMailer.php"); use PHPMailer\PHPMailer\SMTP; use PHPMailer\PHPMailer\PHPMailer; $mail = new PHPMailer(); $conn = new mysqli('localhost', 'root', 'root'); mysqli_select_db($conn, 'dailyplay'); $setSql = "SELECT id, name, description FROM genres"; $setRec = mysqli_query($conn, $setSql); $columnHeader = "ID"."\t"."Name"."\t"."Description"; $setData = ''; while ($rec = mysqli_fetch_row($setRec)) { $rowData = ''; foreach ($rec as $value) { $value = '"' . $value . '"' . "\t"; $rowData .= $value; } $setData .= trim($rowData) . "\n"; } // 第一步:先将内容写入服务器本地临时文件,路径需为PHP有权限读写的目录 $excelContent = ucwords($columnHeader) . "\n" . $setData . "\n"; // 示例路径,可自行修改,需确保目录存在且权限不低于755 $tempFilePath = __DIR__ . '/INTRANSIT_Report.xls'; file_put_contents($tempFilePath, $excelContent); try { //Server settings $mail->SMTPDebug = SMTP::DEBUG_OFF; $mail->isSMTP(); $mail->Host = 'smtp.gmail.com'; $mail->SMTPAuth = true; $mail->Username = 'USERNAME_HERE'; $mail->Password = 'PASSWORD_HERE'; $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; $mail->Port = 587; //Recipients $mail->setFrom('EMAIL_HERE', 'USERNAME_HERE'); $mail->addAddress('RESIPIENT_HERE', 'USERNAME_HERE'); // 加载服务器上实际存在的文件作为附件 $mail->addAttachment($tempFilePath, 'Report.xls'); //Content $mail->isHTML(true); $mail->Subject = 'Here is the subject'; $mail->Body = 'This is the HTML message body <b>in bold!</b>'; $mail->send(); } catch (Exception $e) { // 此处不要直接echo,避免污染下载文件内容,可写入日志记录错误 } // 第二步:邮件发送完成后再输出下载头和文件内容 header("Content-type: application/octet-stream"); header("Content-Disposition: attachment; filename=INTRANSIT_Report.xls"); header("Pragma: no-cache"); header("Expires: 0"); echo $excelContent; // 可选:删除服务器端临时文件释放空间 unlink($tempFilePath); exit; ?>
注意事项
- 请提前创建代码中存储临时Excel的目录,并且给与PHP运行进程读写权限,避免文件写入失败
- Gmail发信需要开启账号的「低安全性应用访问」或者使用应用专用密码,否则会触发发信拦截
内容的提问来源于stack exchange,提问作者vinay nischal
相关产品推荐
相关产品推荐

