【问题标题】:Check if file exist before renaming file upon upload在上传时重命名文件之前检查文件是否存在
【发布时间】:2012-11-07 08:11:26
【问题描述】:

我需要帮助添加功能以在上传时检查文件是否存在。

这是upload.php 代码在上传时的样子:

$file_name = $HTTP_POST_FILES['ljudfil']['name'];
$random_digit=rand(0000,9999);
$mp3 ='.mp3';
$pdf ='.pdf';
$datum = date('Ymd'); 
$new_file_name=$random_digit.$file_name;
$target_path1 = $target_path . $orgnr . '_' . $gsm . $pdf; 

$target_path3 = $target_path . 'AC' . $datum . $new_file_name . $mp3; 
$target_path11 = $target_path4 . $orgnr . '_' . $gsm . $pdf; 

$target_path33 = $target_path4 . 'AC' . $datum . $new_file_name . $mp3;
$targetljudfilftp = 'AC' . $datum . $new_file_name . $mp3;

move_uploaded_file($_FILES['avtalsfil1']['tmp_name'], $target_path1);
move_uploaded_file($_FILES["ljudfil"]["tmp_name"], $target_path3);
$sql = "INSERT INTO affarer (tid, cid, orgnr, ljudfilftp) VALUES 
        (CURDATE(),'$date','$cid','$orgnr', '$targetljudfilftp')";

如您所见,它重命名上传的文件,包括一个随机数。

有时,它会将文件重命名为已经存在的数字。

发生这种情况时,它会覆盖我服务器上的前一个文件。

那么,在重命名之前,如何添加一个函数来检查目标名称是否存在?

【问题讨论】:

    标签: php upload rename


    【解决方案1】:

    你可以使用

    if (file_exists($target_path1))
    

    验证文件是否存在。

    不过,你会做得更好,改变策略并雇用tempnam

    $target_path  = tempnam ($target_path, 'AC' . $datum . $file_name . $mp3)
    

    这将创建诸如“AC_2012_Anacreon.mp3_xTfKxy”之类的文件但您可以保证它是唯一的,即使使用file_exists 也会使您面临并发冲突的风险。

    当然该文件不再具有.mp3 扩展名,因此您在扫描目录并提供文件以供下载时必须考虑到它。

    一个仍然不安全,但可能更简单的方法是这样的:

    for(;;)
    {
        $newname = // some strategy to generate newname, including a random
        if (!file_exists($newname))
            touch($newname);
        if (!filesize($newname))
            break;
    }
    

    或者您可以使用lock 文件来保证没有并发(因此,file_exists 将返回真相,并且它将保持真相):

    $fp = fopen('.flock', 'r+');
    if (flock($fp, LOCK_EX))
    {
        for(;;)
        {
            $newname = // some strategy to generate newname, including a random
            if (!file_exists($newname))
            {
                // this creates the file uniquely for us.
                // all other writers will find the file already there
                touch($newname);
            }
        }    
        flock($fp, LOCK_UN);
    }
    else
        die("Locking error");
    fclose($fp);
    // $newname is now useable.
    

    【讨论】:

      【解决方案2】:

      使用file_exists 内置函数。

      【讨论】:

        【解决方案3】:

        您可以通过使用(例如)基于时间的方法来更改创建随机 digists 的方式

        $random_digit = microtime(TRUE);

        【讨论】:

          【解决方案4】:

          你可以如下使用

          $random_digit = time();

          【讨论】:

          • 这将保证如果两个上传发生在同一秒内。在流量较低的网站上,它大部分时间都可以工作,但在上传高峰时段:-) 你可能会遇到麻烦。
          【解决方案5】:

          不使用'rand'函数会产生重复的数字,你可以使用'uniqid'php函数,它返回一个唯一的id(http://www.php.net/manual/en/function.uniqid.php)。

          如果您仍想使用“rand”,您可以使用“file_exists”函数,生成的文件名作为参数(http://www.php.net/manual/en/function.file-exists.php),但如果文件存在,则必须重新生成文件名,因此您将迭代每个文件存在的时间。

          最后考虑使用全时日期('Ymdhis') 格式而不是关闭日期('Ymd'),也可以通过调用time() 函数来使用时间戳(http://www.php.net/manual/en/function.time.php

          阿纳斯,

          【讨论】:

            【解决方案6】:
            if (file_exists($random_digit)) {
               $random_digit = rand(0000,9999);
            }
            

            【讨论】:

            • 注意:文件不是由数字单独制作的。此外,不能保证您只会有 一个 碰撞。因此,您最好允许while 循环,并且可能在适当次数的尝试后退出“安全计数器”,表明可能没有剩余的空闲数字。
            猜你喜欢
            • 2013-12-02
            • 2012-04-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-02-20
            • 2019-03-07
            • 2016-09-21
            相关资源
            最近更新 更多