【问题标题】:phpMailer attachmentphpMailer 附件
【发布时间】:2011-09-13 10:28:39
【问题描述】:

在将文件上传到我的服务器后,我正在使用它来将文件附加到邮件中:

for ($i = 0; $i <= 2; $i++)
{
    $mail->AddAttachment($locatie.$_FILES['uploaded'.$i]['name'], $_FILES['uploaded'.$i]['name']);
}

添加附件是可选的,但是当没有上传文件时会报错:无法访问文件

如何防止出现这个错误?

【问题讨论】:

  • $locatie 代表什么?
  • @hakre $locatie = 'uploads/';
  • 您是将上传的文件移到那里还是仍然在临时上传文件夹中?

标签: php attachment phpmailer


【解决方案1】:

先看这里如何处理文件上传:

Handling file uploads

您需要参考临时文件名。这是获取实际文件名所必需的,而不仅仅是文件名。

$_FILES['userfile']['tmp_name']

所以访问$_FILES['userfile']['name']获取附件的书面文件名和$_FILES['userfile']['tmp_name']指定上传的实际文件(数据)。

大致放入您的代码中,incl. a validation 您也应该验证它实际上是文件上传:

for ($i = 0; $i <= 2; $i++)
{
    # ignore file that have not been uploaded
    if (empty($_FILES['uploaded'.$i])) continue;

    # get the data of the file
    $fileName = $_FILES['uploaded'.$i]['name'];
    $filePath = $_FILES['uploaded'.$i]['tmpname'];

    # add only if the file is an upload
    is_uploaded_file($filePath) 
      && $mail->AddAttachment($filePath, $fileName)
      ;
}

注意事项

您的代码将两个工作混合在一起。这让您难以调试和改进 - 以及处理文件/系统问题和安全性等问题。

我建议您采用一种不同的方法:一步一步地做。在您的情况下,即 1.) 处理文件上传并收集您需要的数据,2.) 添加这些附件。

您可以通过查看 PHP 手册来改进第一部分。如果你想支持多个文件的上传,我建议你定位于页面Uploading multiple files给出的建议。然后处理文件上传并形成一个数组,其中包含客户端计算机上的文件名和服务器系统上每个条目的路径。

// see PHP Manual for multi file uploads, this is based on it
$validAttachments = array();
foreach($_FILES['userfile']['name'] as $index => $fileName)
{
    $filePath = $_FILES['userfile']['tmp_name'][$index];
    if(is_uploaded_file($filePath))
    {
        $attachment = new stdClass;
        $attachment->fileName = $fileName;
        $attachment->filePath = $filePath;
        $validAttachments[] = $attachment;
    }        
}

如果该部分已经有错误,您知道它与文件上传过程有关。这是未经测试的代码,所以只是说明一个方向。

在第二步中,您可以遍历这样的数组并添加附件:

foreach($validAttachments as $attachment)
{
    $mail->AddAttachment($attachment->filePath, $attachment->fileName);
}

然后,您可以更好地检查不同部分中的错误,而不会将一个问题与另一个问题混为一谈。

【讨论】:

  • 我已将此应用到我的脚本中,但它会使服务器过载。我已在上传部分将其添加到我的循环中: $temp_name.$i = $_FILES['uploaded'.$i]['tmp_name'];然后是附件 if(is_uploaded_file($temp_name.$i))
  • Muiter,这样做:首先重写文件上传部分的脚本。 PHP 支持内置多个文件上传,请查看手册如何比您做得更好。然后您获取所有有效文件的列表(并且您已经验证了程序流程)之后,您就可以轻松地添加附件了。
  • 我添加了更多示例代码以更好地说明我的最后一条评论。希望这是有用的,我知道当自己陷入问题时有时会很困难。
  • 干得好@hakre,这对我来说是一个新的挑战!
【解决方案2】:

在添加附件之前,您应该检查上传的文件是否存在,例如与fopen

【讨论】:

  • 我试过 if(file_exists($locatie.$_FILES['uploaded'.$i]['name'])) 但仍然是错误。
【解决方案3】:

解决方案

for ($i = 0; $i <= 2; $i++)
{
    if (file_exists($locatie.$_FILES['uploaded'.$i]['tmp_name'])) {
        $mail->AddAttachment($locatie.$_FILES['uploaded'.$i]['tmp_name'], $_FILES['uploaded'.$i]['name']);
    }
}

更新

您使用$locatie.$_FILES['uploaded'.$i]['name'] 而不是$locatie.$_FILES['uploaded'.$i]['tmp_name'] 作为要加载的文件。上传文件时,它会使用临时名称重命名并放置在临时文件夹中。这就是你会得到它的地方,这就是为什么你需要用$locatie.$_FILES['uploaded'.$i]['tmp_name']引用它

【讨论】:

    【解决方案4】:

    我已经能够使用计数器解决这个问题:

    $locatie = 'uploads/';
    $upload_count = -1;
    
        for ($i = 0; $i <= 2; $i++)
        {
            if($_FILES['uploaded'.$i]['type'] != 'application/octet-stream')  // Geen php files
            {
                $folder = $locatie.basename($_FILES['uploaded'.$i]['name']) ;           
                if(move_uploaded_file($_FILES['uploaded'.$i]['tmp_name'], $folder))
                {
                    $upload_count ++;
                }
            }
    

    循环查找附件:

    for ($i = 0; $i <= $upload_count; $i++)
    {
        $mail->AddAttachment($locatie.$_FILES['uploaded'.$i]['name'], $_FILES['uploaded'.$i]['name']);
    }
    

    【讨论】:

      【解决方案5】:

      同意@patapizza,但在检查文件系统之前(无论如何你都应该这样做),你也可以只检查 $_FILES 之类的

      for ($i = 0; $i < count($_FILES); $i++){
          // only iterate over the number of files you actually have
      }
      

      【讨论】:

      • 如果只上传一个文件要附加怎么办。
      • 对不起,我没有更精确,但你的 for 循环显然应该只迭代你拥有的项目。我会相应地更新答案。
      • 您能否更新问题并显示您目前获得的完整代码?
      • @konsolenfreddy 查看我在本主题中添加的解决方案。
      【解决方案6】:

      在添加附件之前,您需要检查该文件是否实际上传/存在。类似的东西

      for ($i = 0; $i <= 2; $i++)
      {
          if (file_exists($locatie.$_FILES['uploaded'.$i]['tmp_name'])) {
              $mail->AddAttachment($locatie.$_FILES['uploaded'.$i]['tmp_name'], $_FILES['uploaded'.$i]['name']);
          }
      }
      

      【讨论】:

      • 看看 hakre 的答案——试试$locatie.$_FILES['uploaded'.$i]['tmp_name']。我已经更新了答案——请检查。
      • 无论如何-如果您还没有这样做,请查看this
      • 抱歉,无意中编辑了您的答案,弄得一团糟。 ://
      • @Shef,不用担心,低于 2000 的声誉并且您的编辑进入 建议编辑 队列。即使已提交,也始终可以将帖子回滚到早期版本。 :)
      【解决方案7】:

      不确定这是否完全符合您的要求,但这就是我附加多个上传文件并保留网络表单中的原始文件名的方式。用户的错误处理/消息传递不会为 UPLOAD_ERR_NO_FILE 提供错误,因为文件上传是可选字段,但仍会处理 foreach 循环中的每个输入字段。

      foreach ($_FILES["userfile"]["error"] as $key => $error) 
          {
            if ($error == UPLOAD_ERR_OK) {
              $tmp_name = $_FILES["userfile"]["tmp_name"][$key];
              $name = $_FILES["userfile"]["name"][$key];
              $mailer->AddAttachment($tmp_name, $name);
              }
      
            $name = $_FILES["userfile"]["name"][$key];
            switch($error){
            case UPLOAD_ERR_INI_SIZE: echo $errmsg1.$name.$errmsg2;
      break;
            case UPLOAD_ERR_FORM_SIZE: echo $errmsg1.$name.$errmsg2;
      break;     
            case UPLOAD_ERR_PARTIAL:  echo $errmsg1.$name.$errmsg2; 
      break;
            case UPLOAD_ERR_NO_FILE: 
            break; 
            case UPLOAD_ERR_NO_TMP_DIR: echo $errmsg1.$name.$errmsg2;
      break; 
            case UPLOAD_ERR_CANT_WRITE: echo $errmsg1.$name.$errmsg2;
      break;
            case UPLOAD_ERR_EXTENSION: echo $errmsg1.$name.$errmsg2;
      break;
            } 
      }
      

      【讨论】:

        猜你喜欢
        • 2016-10-28
        • 2017-04-29
        • 2013-08-07
        • 2013-02-17
        • 2012-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多