如何在Symfony/Mailer中动态添加上传的文件?
Symfony Mailer 动态添加上传文件附件问题解决
我正在使用Symfony Mailer包实现邮件上传文件功能,当前环境为PHP 8.2和symfony/mailer v6.2。表单允许用户最多上传4个文件,官方文档仅展示了静态添加附件的方法,但我需要通过解析上传的$_FILES数组来动态添加附件。目前我的代码触发了500错误,原代码如下:
<?php require('lib/composer/vendor/autoload.php'); use Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Mailer; use Symfony\Component\Mime\Email; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Part\DataPart; use Symfony\Component\Mime\Part\File; $user = ''; $password = ''; $transport = Transport::fromDsn('smtp://' . $user . ':' . $password . '@domain.co.uk:25'); $mailer = new Mailer($transport); $email = (new Email()) ->from(new Address('from@email.co.uk', 'Name')) ->to('my@email.co.uk') ->subject('Hi this is a test using Symfony Mailer!') ->text('Sending emails is fun again!') ->addPart(new DataPart(new File('test.png'), 'Attached File')) ->html('<p>See Twig integration for better HTML integration!</p>'); // Check for an uploaded file for($i=0; $i<=3; $i++) { if(!empty($_FILES['uploaded_file']['tmp_name'][$i])) { $email->addPart(new DataPart(new File($_FILES['uploaded_file']['tmp_name'][$i]), $_FILES['uploaded_file']['name'][$i])); } } $mailer->send($email); ?> <form method='post' enctype='multipart/form-data' action=''> <input class='upload_file' type='file' name='uploaded_file[]' id='upload_file1'> <input class='upload_file' type='file' name='uploaded_file[]' id='upload_file2'> <input class='upload_file' type='file' name='uploaded_file[]' id='upload_file3'> <input class='upload_file' type='file' name='uploaded_file[]' id='upload_file4'> <input type='submit'> </form>
问题原因
触发500错误的核心原因是未正确处理$_FILES数组的结构:当用户未上传满4个文件时,$_FILES['uploaded_file']['tmp_name']的索引不连续,固定遍历0-3下标会导致Undefined Offset错误;此外,直接使用原始$_FILES数据缺少上传有效性验证,存在安全风险。
修正后的代码
<?php require('lib/composer/vendor/autoload.php'); use Symfony\Component\Mailer\Transport; use Symfony\Component\Mailer\Mailer; use Symfony\Component\Mime\Email; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Part\DataPart; use Symfony\Component\Mime\Part\File; $user = ''; $password = ''; $transport = Transport::fromDsn('smtp://' . $user . ':' . $password . '@domain.co.uk:25'); $mailer = new Mailer($transport); $email = (new Email()) ->from(new Address('from@email.co.uk', 'Name')) ->to('my@email.co.uk') ->subject('Hi this is a test using Symfony Mailer!') ->text('Sending emails is fun again!') ->addPart(new DataPart(new File('test.png'), 'Attached File')) ->html('<p>See Twig integration for better HTML integration!</p>'); // 动态处理上传文件 if (!empty($_FILES['uploaded_file']) && is_array($_FILES['uploaded_file']['tmp_name'])) { foreach ($_FILES['uploaded_file']['tmp_name'] as $index => $tmpPath) { // 验证文件是否合法上传且非空 if (is_uploaded_file($tmpPath) && filesize($tmpPath) > 0) { $fileName = $_FILES['uploaded_file']['name'][$index]; $email->addPart(new DataPart(new File($tmpPath), $fileName)); } } } $mailer->send($email); ?> <form method='post' enctype='multipart/form-data' action=''> <input class='upload_file' type='file' name='uploaded_file[]' id='upload_file1'> <input class='upload_file' type='file' name='uploaded_file[]' id='upload_file2'> <input class='upload_file' type='file' name='uploaded_file[]' id='upload_file3'> <input class='upload_file' type='file' name='uploaded_file[]' id='upload_file4'> <input type='submit'> </form>
关键改进点
- 遍历实际上传的文件:用
foreach替代固定下标循环,避免索引不存在的错误; - 安全验证:通过
is_uploaded_file()确保文件是合法HTTP POST上传,防止恶意文件注入; - 空文件过滤:用
filesize($tmpPath) > 0排除用户选择后取消上传的空文件; - 健壮性提升:先判断
$_FILES数组是否存在,避免未提交文件时的报错。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

