2010-04-25 54 views
0

我正在尝试将用户提交的文章添加到我的网站(仅限管理员)。每篇文章都有一个选项可以上传3张图片。我的数据库建立这样如何在php中命名上传的文件以防止被覆盖?

文章

id 
user_id 
title 
body 
date_added 
last_edited 

照片

id (auto_increment) 
article_id 

首先,我保存的文章在数据库中,然后我上传照片(临时)然后创建一个新的照片在数据库中记录保存article_id。然后,我将上传的照片重命名为与照片记录的主键相同,并成为png。

$filename = $photo->id . '.png';

我想这是防止文件的形式被覆盖的好方法。这对我来说似乎有缺陷。有关如何保存我的记录和照片的任何建议?

谢谢

+0

什么问题? – Ben 2010-04-25 03:32:25

+0

*(参考)* http://de3.php.net/manual/en/function.uniqid.php – Gordon 2010-04-25 10:06:41

回答

1

仅仅使用数据库主键来命名文件没有任何问题。

我看到的唯一真正的缺点是,你最终用相当无用的文件名。有人可能会抱怨道,更多的描述性名称将有助于搜索引擎排名等。

另一个答案指出,重命名文件以.png结尾不会使其成为png。如果您想实际转换图像格式,您可能需要查看PHP的内置GD库(或查看ImageMagick)。

+0

那里有真话。 – Ben 2010-04-25 03:53:22

1

哈希它们。

我已经使用PHP的MD5函数在图片上传到图库时对图片进行哈希处理。它有两个主要的好处:不同的图像不会相互覆盖,相同的图像。这意味着每个独特的图片将有一个独特的名字。接受上传,散列存储的数据,建立文件名(hash.extension),检查现有文件。如果存在,请删除临时文件并仅使用现有副本。否则,重命名临时文件并保留它。您可能需要跟踪链接到每个文件的内容(以确保您不会删除其他地方使用的文件),但它可以在重复文件上节省大量空间,并且是获取唯一名称的简单方法。

而且,你不能只重命名使用PNG扩展名的文件,你需要将它们转换成PNG格式或保存原来的扩展名。使用错误的扩展名可能会在某些地方,某些浏览器中导致问题,而且通常不正确。

+0

这绝对值得考虑。在某些情况下,可能会方便地拥有同一文件的多个副本(以便一个用户的删除不会全部删除),而其他情况下,由实际文件内容定义唯一性的空间节省特性可能非常有用。 – 2010-04-25 03:47:00

1

对于它的价值,这里是我的文件上传类的方法包括我,以确保我不会覆盖现有文件。我传递上传文件名称($ _FILES [$ img_field] [“name”])和目录以将文件保存为参数,因此这仍然是常规方法。

private function unique_file_upload($filename, $dir) { 
     $filename = preg_replace("/[^.\w]/",'_',$filename); 
     $filename = preg_replace("/__+/",'_',$filename); 
     preg_match("/^(.*)\.(\w{2,4})$/",$filename,$f); 
     if (file_exists($dir . $filename)) { 
      $num = 1; 
      while (file_exists($dir . $filename)) { 
       preg_match("/^(.*)\.(\w{2,4})$/",$filename,$f); 
       preg_match("/(\d+)$/",$f[1],$n); 
       if ($n[1]) { 
        $x = $n[1]; 
        $num = $n[1] + 1; 
        $num .= '.'; 
        $filename = preg_replace("/$x\./",$num,$filename); 
       } 
       else { 
        $filename = $f[1] . $num . '.' . $f[2]; 
       } 
      } 
     } 
     return $filename; 
    } 
1

如果图像使用自动递增主键作为名称,那么绝对不可能有两个具有相同名称的图像。

散列或做任何额外的事情来确保名称中的唯一性毫无价值。更重要的是,这意味着在数据库中添加一个额外的图像名称字段。

图像可能被覆盖的唯一方法是,如果您重置数据库自动增加计数器,并且为此,您需要删除表上的以前的记录,否则计数器将再次由DBMS重新计算为最高ID记录在桌子上。

换句话说,使用你的算法,你将不会有两个同名的图像。

0

正确的方法是将文件与关联记录的主键ID一起存储。要处理“但这只是一个无用的号码”,你可以将原始文件名存储在“照片”表中。如果你允许多种图像类型,你也可以存储MIME类型。

然后,您使用一个简单的脚本从数据库中检索文件的名称,并使用Content-disposition: attachment; filename=$filename标题将其提供给客户端。这样,即使您的服务器上的文件名是(比如说)“3527”,客户端也会看到“originalimagefilename.jpg”或其他任何内容的下载。