在PHP Mailer中上载文件的正确方法

在PHP Mailer中上载文件的正确方法,php,file-upload,phpmailer,Php,File Upload,Phpmailer,嗨,有人能帮我处理和测试我在PHPMailer中上传的文件的代码吗?它基本上检查文件是否正确,然后使用用户名加上字段名以及日期和时间重命名文件名。有多个文件,但我没有使用多个上传程序,而是使用单独的字段,这样我就可以跟踪哪个文件是哪个文件 脚本似乎正常工作,php错误日志中没有错误,但我在上一篇文章中被告知这是一个安全缺陷,我的“pathinfo调用应该测试实际文件的tmp_名称的路径,而不是给定的原始名称。这是一个严重的安全缺陷。” 不幸的是,我不确定pathinfo的两种用法中哪一种是错误的

嗨,有人能帮我处理和测试我在PHPMailer中上传的文件的代码吗?它基本上检查文件是否正确,然后使用用户名加上字段名以及日期和时间重命名文件名。有多个文件,但我没有使用多个上传程序,而是使用单独的字段,这样我就可以跟踪哪个文件是哪个文件

脚本似乎正常工作,php错误日志中没有错误,但我在上一篇文章中被告知这是一个安全缺陷,我的“pathinfo调用应该测试实际文件的tmp_名称的路径,而不是给定的原始名称。这是一个严重的安全缺陷。”

不幸的是,我不确定pathinfo的两种用法中哪一种是错误的。如果我将$imageFileExt的$file[“name”]更改为$file[“tmp_name”],那么我不会获得文件扩展名,如果我将$imageFileType的$file[“name”]更改为$file[“tmp_name”],那么我只会得到错误的文件错误。任何帮助都将不胜感激。谢谢

    foreach ( $_FILES as $key => $file ) {
    
    //get the file extension
                $imageFileExt = strtolower( pathinfo( $file["name"], PATHINFO_EXTENSION ) );
    
//change the name of each file in $_FILES array to 
//the persons name plus file field plus date plus time plus file extension 
//such as :joe_bloggs_bank_statement_1_9_10_21_10_55.jpg
//and joe_bloggs_pay_slip_1_9_10_21_10_55.jpg
                $file['name'] = clean($_POST['appName']). "_" . $key . "_" . $dateKey . "." . $imageFileExt;
    
    // get the file type
                $target_file = $target_dir . basename($file["name"]);
                $imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
    
    
    // get file size
                $check = getimagesize($file["tmp_name"]);
                if($check === false) {
                    $fileMessage .=  $key."=noimage,";
                    $uploadOk = 0;
                }
    
    // Allow certain file formats
    
            else if($imageFileType !== "jpg" && $imageFileType !== "png" && $imageFileType !== "jpeg"
                   && $imageFileType !== "gif" ) {
                    $fileMessage .=  $key."=wrongfile,";
                    $uploadOk = 0;
                }
    
    // Check if file already exists
            else if (file_exists($target_file)) {
                    $fileMessage .=  $key."=fileexists,";
                    $uploadOk = 0;
                }
    
    
    // Check file size
            else if ($file["size"] > 20000000) { //20mb
                    $fileMessage .=  $key."=toobig,";
                    $uploadOk = 0;
                }
    // creates a set of links to the uploaded files on the server 
    // to be placed in the body of the email (the files themselves do not get attached in the email
                $fileString .= strtoupper($key).": <a href='example.com/uploads/".$file['name']."'>".$file['name']."</a><br>";
    
    
            }
foreach($\u文件为$key=>$file){
//获取文件扩展名
$imageFileExt=strtolower(路径信息($file[“name”],路径信息扩展名));
//将$\u FILES数组中每个文件的名称更改为
//“人员姓名+文件”字段+日期+时间+文件扩展名
//例如:joe_bloggs_bank_statement_1_9_10_21_10_55.jpg
//还有joe_bloggs_pay_slip_1_9_10_21_10_55.jpg
$file['name']=clean($_POST['appName'])。“$key.”.“$dateKey.”.“$imageFileExt;
//获取文件类型
$target_file=$target_dir.basename($file[“name”]);
$imageFileType=strtolower(路径信息($target_文件,路径信息_扩展名));
//获取文件大小
$check=getimagesize($file[“tmp_name”]);
如果($check==false){
$fileMessage.=$key.=noimage,”;
$uploadOk=0;
}
//允许某些文件格式
如果($imageFileType!==“jpg”&&&$imageFileType!==“png”&&&$imageFileType!==“jpeg”
&&$imageFileType!=“gif”){
$fileMessage.=$key.=errolefile;
$uploadOk=0;
}
//检查文件是否已经存在
else if(文件_存在($target_文件)){
$fileMessage.=$key.“=fileexists,”;
$uploadOk=0;
}
//检查文件大小
如果($file[“size”]>20000000){//20mb
$fileMessage.=$key.=toobig,”;
$uploadOk=0;
}
//创建一组指向服务器上上载文件的链接
//放置在电子邮件正文中(文件本身不会附加在电子邮件中
$fileString.=strtoupper($key)。“:
”; }
我想你可能会被这些东西之间的区别弄糊涂。文件本身是由用户提供的一堆字节。它的文件名是关于该文件的元数据,也是由用户提供的。tmp_名称也是关于该文件的元数据,但是是安全的,因为它不是由用户提供的

在任何时候都不能使用
move\u uploaded\u file()
is\u uploaded\u file()
。这些都是在脚本运行之前验证上传的文件是否是PHP正确处理的真实上传文件所必需的。这是在信任
$\u文件中的任何其他文件之前应该做的第一件事

不信任名称>属性的原因是文件名可以用作攻击向量,例如通过路径遍历序列(如<代码>…/<代码> >)、SQL逃逸(<代码> >代码>),或者在shell上下文中使用意外字符(<代码> \/COD>,<代码> <代码> >等).tmp_name

tmp_name
由PHP本身生成,不包含用户提供的数据,尽管您需要使用上面提到的函数来确保这是真实的数据,而不是注入的数据 由用户提供

类似地,文件名也不能准确地告诉您文件的类型——搜索“多语言文件”以了解这可能是一个问题的原因

您没有显示
clean()
函数中的内容,因此我们无法确定它的功能是否有效


在您之前的问题中,我向您介绍了。这说明了如何安全地处理上载。例如,它采用提供的任何名称并对其进行哈希运算,生成一个字符串,保证不会受到用户提供的数据的影响。

再次感谢您的回答,我尝试应用了您之前给我的示例,但该示例使用了倍数我不使用文件上传器,相反,我使用9个单独的文件上传器,它们都是必填字段。其次,我正试图按照您在这里所说的,并将其纳入我的代码中,但我很难确定代码中的第一个内容。我会尝试让它工作,然后运行代码,如果可以的话。我是否应该直接编辑这是我最初的问题吗?好的,我想我已经解决了。我将创建一个新的帖子,如果效果更好,那么我会将此标记为已回答。