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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 22:02:47