PHP图片上传 - 重命名不丢失扩展名?

3

我目前拥有:

$file_name = $HTTP_POST_FILES['uid']['name'];
$random_digit=rand(0000,9999);
$new_file_name=$random_digit.$file_name;
$path= "uploads/images/users/".$new_file_name;
if($ufile !=none)
{
    if(copy($HTTP_POST_FILES['uid']['tmp_name'], $path))
    {
        echo "Successful<BR/>"; 
        echo "File Name :".$new_file_name."<BR/>"; 
        echo "File Size :".$HTTP_POST_FILES['uid']['size']."<BR/>"; 
        echo "File Type :".$HTTP_POST_FILES['uid']['type']."<BR/>"; 
    }
    else
    {
        echo "Error";
    }
}

这会在当前文件名前生成一个随机数,例如4593example.jpg。但我只想将整个文件名重写为4593.jpg,删除当前名称(例如example)。当我尝试这样做时,我丢失了扩展名(.jpg)。希望能得到帮助。
4个回答

4
如果您只处理图像,我建议使用 getimagesize() 来检测图像类型,并根据该类型为新文件命名扩展名。
这样,您就不必依赖用户提供的扩展名(可能是错误的)。
示例代码如下:
$extensions = array(
  IMAGETYPE_JPG => "jpg",
  IMAGETYPE_GIF => "gif",
  IMAGETYPE_PNG => "png",
  IMAGETYPE_JPEG2000 => "jpg",
  /* ...... several more at http://php.net/manual/en/image.constants.php 
            I'm too lazy to type them up */

 );

$info = getimagesize($_FILES['uid']['tmp_name']); 
$type = $info[2];

$extension = $extensions[$type];

if (!$extension) die ("Unknown file type");

move_uploaded_file($_FILES['uid']['tmp_name'], $path.".".$extension);

另外:

  • 正如@alex所说,您的方法存在随机名称冲突的风险。您应该添加file_exists()检查来防止这些问题(例如,创建一个循环,直到找到尚不存在的新随机数为止)。

  • HTTP_POST_FILES已被弃用,请改用$_FILES

  • 我强烈建议您使用move_uploaded_file()而不是copy(),后者容易受到攻击。


使用 copy() 可能会发生哪些攻击?谢谢。 - alex
@alex,存在/曾经存在一个漏洞——move_uploaded_file()是为了应对这个漏洞而引入的。我曾经在2000年左右用这个方法闯进了一个朋友的phpBB :) 等等,我看看能否找到链接。 - Pekka
1
@alex,很奇怪,我现在找不到链接了。无论如何,它的要点是你可以覆盖 $_FILES["xyz"]["tmp_name"] 并将本地文件路径放入其中。如果你知道攻击的应用程序结构,你就可以通过这种方式获取数据库配置文件等信息。copy()会愚蠢地将配置文件复制到新位置,如果上传是为了头像图片,则可以从中下载它。move_uploaded_file() 只会移动实际上传的文件。 - Pekka

3
你可以使用以下代码获取原始扩展名: $extension = strrchr($HTTP_POST_FILES['uid']['tmp_name'], '.'); 然后你可以将扩展名添加到变量$new_file_name中,像这样: $new_file_name = $random_digit . $file_name . '.' . $extension;

3
$ext = pathinfo($filename, PATHINFO_EXTENSION);

$newFilename = $random_digit . '.' . $ext;

顺便问一下,如果随机数冲突会发生什么情况(可能会在接下来的10年内发生)?

有许多更好的命名方法 - 例如,文件名的哈希值和 time() 理论上永远不会冲突(尽管实际上哈希碰撞确实会发生)。


1
你可以使用这段代码:
$file_name = $HTTP_POST_FILES['uid']['name']; $random_digit=rand(0000,9999); 
$extension= end(explode(".", $HTTP_POST_FILES['uid']['name']));
$new_file_name=$random_digit.'.'.$extension; $path= "uploads/images/users/".$new_file_name; if($ufile !=none) { if(copy($HTTP_POST_FILES['uid']['tmp_name'], $path)) { echo "Successful
"; echo "File Name :".$new_file_name."
"; echo "File Size :".$HTTP_POST_FILES['uid']['size']."
"; echo "File Type :".$HTTP_POST_FILES['uid']['type']."
"; } else { echo "Error"; } }

享受!!!!!!!!!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接