PHP 检查文件名是否正在使用,然后在上传时添加数字

PHP check if filename is in use and then add number on upload

我正在尝试制作一个 "send email" 表单,在发送电子邮件之前将文件上传到文件夹。文件的路径随后会显示在电子邮件中,但如果文件确实存在,我不希望它们被覆盖,但我想添加一个数字。

我编写了这个小代码,但它不起作用!

错误说:

Parse error: syntax error, unexpected '$name_of_uploaded_file' (T_VARIABLE) in /customers/8/5/6/HOMEPAGE/httpd.www/php/mailtest2.php on line 49

如果文件不存在,下面的脚本现在会上传文件。如果该文件确实存在,则什么也不会发生。脚本应该结束。

脚本已修改为不将“_1”添加到文件名并将文件保存在文件夹中的原因。现在它将文件保存在文件夹中并出现错误:复制上传文件时出错

有人可以向我解释我做错了什么吗?

现在显示所有代码来调试这个:

<?php
//Uploaded file 1

//Settings
$max_allowed_file_size = 2000; // size in KB
$allowed_extensions = array("jpg", "jpeg", "gif", "bmp", "pdf");
error_reporting(E_ALL);

//Upload folder
//name also used later on mail
$name = $_POST['name'];
$d = date('d.m.y');
$varfoldername = "../receivedfiles/$name$d/";
if(!is_dir($varfoldername)) {
mkdir($varfoldername , 0777 , true);
}
$upload_folder = $varfoldername;

//Get the uploaded file information
$name_of_uploaded_file =
    basename($_FILES['uploaded_file']['name']);


//Validations
//----- Check if files exists and adds _X to it -----
$original_name_of_file = pathinfo($name_of_uploaded_file, PATHINFO_FILENAME);
$extension =  pathinfo($name_of_uploaded_file, PATHINFO_EXTENSION);
$FileCounter = 0;

while (file_exists($varfoldername.$name_of_uploaded_file)) {
     $FileCounter++;
     $name_of_uploaded_file = $original_name_of_file . '_' . $FileCounter . '.' . $extension;
}

//copy the temp. uploaded file to uploads folder
$path_of_uploaded_file = $upload_folder . $name_of_uploaded_file;
$tmp_path = $_FILES["uploaded_file"]["tmp_name"];

if(is_uploaded_file($tmp_path))
{
  if(move_uploaded_file ( $tmp_path,$path_of_uploaded_file ))
  {
    die("Error while copying the uploaded file");
  }
}

//Validate size requirements
$size_of_uploaded_file =
    $_FILES["uploaded_file"]["size"]/1024;//size in KBs

if($size_of_uploaded_file > $max_allowed_file_size )
{
  die("Fejl: Filen er for stor");
}

//------ Validate the file extension -----
//get the file extension of the file
$type_of_uploaded_file =
    substr($name_of_uploaded_file,
    strrpos($name_of_uploaded_file, '.') + 1);
$allowed_ext = false;
for($i=0; $i<sizeof($allowed_extensions); $i++)
{
  if(strcasecmp($allowed_extensions[$i],$type_of_uploaded_file) == 0)
  {
    $allowed_ext = true;
  }
}

if(!$allowed_ext)
{
  die("The uploaded file is not supported file type. \n Send venligst filer af følgende type: .implode(',',$allowed_extensions)");
}

$email = $_POST['email'];
$phone = $_POST['phone'];
$call = $_POST['call'];
$company = $_POST['company'];
$type = $_POST['type'];
$adress = $_POST['adress'];
$hesteid = $_POST['hesteid'];
$hestenavn = $_POST['hestenavn'];
$message = $_POST['message'];
$areacode = $_POST['areacode'];
$land = $_POST['land'];
$formcontent=" Fra: $company \n Navn: $name \n Adresse: $adress , $areacode \n Land: $land \n Telefon: $phone \n Ringes op: $call \n Type: $type \n Hoppens navn og ID: $hestenavn , $hesteid \n Besked: \n $message \n Vedhæftede filer: \n $path_of_uploaded_file";
$recipient = "simon@secret.dk";
$subject = "Besked fra hjemmesiden";
$mailheader = "Fra: $email \r\n";
mail($recipient, $subject, $formcontent, $mailheader) or die("Error!");
header('Location: thank_you.shtml');
?>

PHP documentation 说:

while (file_exists($varfoldername . $name_of_uploaded_file )) 

也许您需要一个 $varfoldername . '/' . $name_of_uploaded_file - 最好是您能给我们一个 var_dump 这两个变量。

您需要使用 . 字符连接(粘在一起)不同的 PHP 变量,因此:

while (file_exists($varfoldername$name_of_uploaded_file )) 

会给你 return 一个解析错误,因为你需要告诉 PHP 你想将两个变量 串在一起 ,所以改用 . 并写:

while (file_exists($varfoldername.$name_of_uploaded_file))  

您可能还需要在两个变量之间添加一个 / 目录分隔符,但这是一个与您当前问题没有直接关系的问题。但它对 print $varfoldername.$name_of_uploaded_file 很有用,看看它是否是正确的文件路径布局(具有所有 / 等)

进一步工作

Hi again I just modified the question. Found two stupid bugs. Now the script runs without error but doesn't add "_1" to the filename. – Simon Jensen

重新排列您的代码:

$FileCounter = 0;
$original_name_of_file = $name_of_uploaded_file;
while (file_exists($varfoldername.$name_of_uploaded_file)) {
     $FileCounter++;
     $name_of_uploaded_file = $original_name_of_file . '_' . $FileCounter . '.' . $extension;
}

这里发生了什么:

  • PHP 在 while 循环中覆盖 $name_of_uploaded_file 这样如果你有 file_1.txt 那么循环中的下一个文件名将是 file_1.txt_2.txt 你可以看到这个覆盖远非完美,你需要保存 Original 文件,然后用增量值覆盖原始文件,然后覆盖 .txt .

  • 您的 $name_of_uploaded_file 的原始值未定义。

  • $FileCounter 为清楚起见,在写入字符串之前递增。

  • 您的 $FileCounter++ 代码将无法运行,因为您通过设置将 $FileCounter 定义为 string在引号中。我已经删除了引号,所以它现在被 PHP 识别为一个整数。

  • 您的 file_exists 呼叫 应该 被引号引起来 PHP 额外的、不必要的工作,而且经常会让你和你的 IDE 感到困惑。有效的引号是:

PHP Logic: I found a quote, I will start a string structure, oh, this part looks like a variable, I will stop the string structure, then concatenate this variable value into the string strucuture, then continue the string, oh, another variable, I will stop the string structure, and then concatenate the second variable into this string, then continue. I found another quote so string finished.

这比清晰简洁地定义两个用 . 连接的变量要大得多。

完整代码:

$name = $_POST['name'];
$d = date('d.m.y');
/***
Ideally folders should NEVER be relative, always base them from the PHP server 
root such as (example only), using $_SERVER['DOCUMENT_ROOT']:
$varfoldername = $_SERVER['DOCUMENT_ROOT']."/data/uploads/receivedfiles/".$name.$d."/";
***/
$varfoldername = "../receivedfiles/".$name.$d."/";
$upload_folder = $varfoldername;

$name_of_uploaded_file = basename($_FILES['uploaded_file']['name']);

$original_name_of_file = pathinfo($name_of_uploaded_file, PATHINFO_FILENAME);
$extension =  pathinfo($name_of_uploaded_file, PATHINFO_EXTENSION);
$FileCounter = 0;

while (file_exists($varfoldername.$name_of_uploaded_file)) {
     $FileCounter++;
     $name_of_uploaded_file = $original_name_of_file . '_' . $FileCounter . '.' . $extension;
}

/***
Now $name_of_uploaded_file will have the numerical appendage as needed.
***/

if(move_uploaded_file( $tmp_path , $varfoldername.$name_of_uploaded_file )){ 
      print "file uploaded!";
    }

重要

不要使用copy,而是使用PHP Move_upload_file :

if(!copy($tmp_path,$path_of_uploaded_file)){ ...

变成

if(move_uploaded_file ( $tmp_path , $path_of_uploaded_file )){ ...

当您可以从中创建一个可重复使用的对象时,就没有太多需要使用这个长方法了。

interface FileUploaderInterface
{
    public function upload($path);
}

class FileUploader implements FileUploaderInterface
{
    protected $File;
    public function __construct($file)
    {
          $this->File = $file;
          return $this;
    }
    public function upload($path)
    {
        if(file_exists($path.$this->File['name']))
        {
            $this->File["tmp_name"] = $this->File["name"] . '-' . time();
            move_uploaded_file($this->File, $path . $this->File["name"]);
            return false;
        }
        else
        {
            move_uploaded_file($this->File, $path . $this->File["name"]);
            return true;
        }
    }
}

只需使用 require_once() 然后使用此代码即可使用:

$obj = new FileUploader($_FILES["fileToUpload"]);
if(!$obj->upload(dirname(__FILE__) . '/example/path/ect')) {
    echo "File existed, we added the time onto the name";
}