NextJS+Axios+PHPMailer发送邮件附件失败求助
解决NextJS+Axios+PHPMailer邮件附件无法传递的问题
前端问题与修正
你的前端核心问题是用JSON格式传递文件,但File对象无法被JSON序列化,且强制设置了application/json请求头,导致后端无法正确解析文件。必须改用FormData封装表单数据,这是文件上传的标准方式。
修改后的前端状态管理与提交代码
const [forma, setForma] = useState({ name: '', mail: '', mobile:'', department:"", title:"", file: null // 初始值改为null,匹配File对象类型 }) const handleSubmita = (e) => { e.preventDefault() console.log(forma) setSpinner(true) // 用FormData封装所有表单数据 const formData = new FormData() formData.append('name', forma.name) formData.append('mail', forma.mail) formData.append('mobile', forma.mobile) formData.append('department', forma.department) formData.append('title', forma.title) if (forma.file) { formData.append('app-file', forma.file) // key与input的name属性保持一致 } axios({ method: 'post', url: process.env.NEXT_PUBLIC_URL_A, // 不要手动设置content-type,让Axios自动处理multipart/form-data格式 data: formData, }) .then((result) => { console.log(result.data) if (result.data == '200') { setSpinner(false) setResultqform(true) } else { setSpinner(false) setError(true) } }) .catch((error) => console.log('error')) }
表单部分无需修改,保持原有结构即可。
后端问题与修正
后端核心问题是错误解析请求格式,且对$_FILES的引用逻辑完全错误。multipart/form-data格式的请求会被PHP自动解析到$_POST和$_FILES全局变量,无需手动读取php://input。
修改后的后端PHP代码
<?php header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Headers: Content-Type'); use PHPMailer\PHPMailer\PHPMailer; // 检查必填字段和文件上传状态 if ( isset($_POST['name']) && isset($_POST['mail']) && isset($_POST['title']) && isset($_POST['mobile']) && isset($_POST['department']) && isset($_FILES['app-file']) && $_FILES['app-file']['error'] === UPLOAD_ERR_OK ) { // 转义HTML特殊字符,防止XSS $name = htmlentities($_POST['name']); $mail = htmlentities($_POST['mail']); $title = htmlentities($_POST['title']); $mobile = htmlentities($_POST['mobile']); $department = htmlentities($_POST['department']); // 获取上传文件基础信息 $fileTmpPath = $_FILES['app-file']['tmp_name']; $fileName = $_FILES['app-file']['name']; $fileSize = $_FILES['app-file']['size']; $fileType = $_FILES['app-file']['type']; // 验证文件类型和大小(可选,按需调整) $allowedTypes = ['application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/pdf']; if (!in_array($fileType, $allowedTypes) || $fileSize > 5 * 1024 * 1024) { // 限制5MB以内 echo "Invalid file type or size"; exit; } // 可选:将文件保存到服务器留档 $uploadDir = 'tmp/'; if (!is_dir($uploadDir)) { mkdir($uploadDir, 0755, true); } $destPath = $uploadDir . $fileName; if (!move_uploaded_file($fileTmpPath, $destPath)) { echo "Failed to save file"; exit; } require_once 'PHPMailer/PHPMailer.php'; require_once 'PHPMailer/SMTP.php'; require_once 'PHPMailer/Exception.php'; $mail = new PHPMailer(true); // 启用异常处理 date_default_timezone_set('Europe/London'); $now = date_create()->format('Y-m-d H:i:s'); try { $mail->isSMTP(); $mail->Host = $Host; $mail->SMTPAuth = true; $mail->Username = $uname; $mail->Password = $pass; $mail->SMTPSecure = 'ssl'; $mail->Port = $port; $mail->CharSet = 'UTF-8'; $mail->setFrom($mailer, 'Mailer'); $mail->addAddress($recipent, $recipent_info); $mail->addReplyTo($mail, $name); // 添加附件:已保存用destPath,无需保存直接用$fileTmpPath即可 $mail->addAttachment($destPath, $fileName); $mail->isHTML(true); $mail->Subject = 'Test'; $mail->Body = "<b>{$name}</b> =name<br><br>"; $mail->Body .= "<b>department:</b> {$department}<br><br>"; $mail->Body .= "<b>title:</b> {$title}<br><br>"; $mail->Body .= "<b>Mobile:</b> {$mobile}<br><br>"; $mail->Body .= "<b>Mail:</b> {$mail}<br><br>"; $mail->Body .= "<b>Time: </b>{$now}"; $mail->send(); echo '200'; } catch (Exception $e) { echo "Error! Mailer Error: {$mail->ErrorInfo}"; } } else { echo "Missing required fields or file upload failed"; } ?>
关键修正点说明
- 前端改用
FormData传递数据,请求头由Axios自动适配multipart/form-data。 - 后端删除手动解析请求的逻辑,直接使用PHP自动处理的
$_POST和$_FILES。 - 正确引用上传文件:
$_FILES['app-file']对应前端input的name属性。 - 添加文件上传验证(错误码、类型、大小),避免无效文件引发错误。
- 支持两种附件添加方式:保存到服务器后添加,或直接使用临时文件路径(临时文件会在请求结束后被PHP自动删除)。
内容的提问来源于stack exchange,提问作者u238
相关产品推荐
相关产品推荐

