2011-05-01 106 views
6

在我的网站上,我让用户上传文件。命名约定上传文件

如果文件有效并上传,它将被移动到一个文件夹(使用PHP)。

所有用户上传到同一个文件夹。

我想我需要重命名上传的文件。

有没有像默认的命名约定让用户上传具有相同文件名的文件?

回答

16

有没有标准约定,但有一对夫妇的最佳实践:


组织您的文件转换成(用户和/或日期)意识到文件夹

喜欢的东西:

/uploads/USER/ or 
/uploads/[USER/]YEAR/[MONTH/[DAY/[HOUR/[MINUTE/]]]] 

这将带来一些好处:


(不)重命名/消毒文件名

重命名或不被选择,你将不得不作出,这取决于你的网站,用户群,你希望成为多么模糊,显然你的架构。您想要一个名为kate_at_the_beach.jpg1304357611.jpg的文件吗?这真的取决于你自己决定,但搜索引擎(显然)像第一个更好。

有一件事你应该做的是总是消毒和规范文件名,我个人只允许下列字符:0-9a-zA-Z_-. - 如果你选择了这个卫生字母。规范化基本上意味着只需将文件名转换为较低或较大的文件名(例如,如果您从区分大小写的文件系统切换到不区分大小写的文件系统(如Windows),则可避免文件丢失)。

这是我在phunction使用一些示例代码(无耻插头,我知道:P):

$filename = '/etc/hosts/@Álix Ãxel likes - beer?!.jpg'; 
$filename = Slug($filename, '_', '.'); // etc_hosts_alix_axel_likes_beer.jpg 

function Slug($string, $slug = '-', $extra = null) 
{ 
    return strtolower(trim(preg_replace('~[^0-9a-z' . preg_quote($extra, '~') . ']+~i', $slug, Unaccent($string)), $slug)); 
} 

function Unaccent($string) // normalizes (romanization) accented chars 
{ 
    if (strpos($string = htmlentities($string, ENT_QUOTES, 'UTF-8'), '&') !== false) 
    { 
     $string = html_entity_decode(preg_replace('~&([a-z]{1,2})(?:acute|cedil|circ|grave|lig|orn|ring|slash|tilde|uml);~i', '$1', $string), ENT_QUOTES, 'UTF-8'); 
    } 

    return $string; 
} 

处理重复文件名

由于上move_uploaded_file()的文档录入状态:

如果目标文件已存在 ,则它将被覆盖。

所以,你叫move_uploaded_file(),你最好检查文件是否已经存在,如果是这样,那么你应该(如果你不想失去你的旧文件)重命名新的文件,通常附加一个时间前/随机/唯一标记之前文件扩展名,做这样的事情:

if (file_exists($output . $filename) === true) 
{ 
    $token = '_' . time(); // see below 
    $filename = substr_replace($filename, $token, strrpos($filename, '.'), 0); 
} 

move_uploaded_file($_FILES[$input]['tmp_name'], $output . $filename); 

这将具有文件扩展名之前插入$token,像我上述的效果。至于$token值的选择,你有几种选择:

  • time() - 确保唯一每秒钟但太烂处理重复文件
  • 随机 - 不是一个很好的主意,因为它不保证独特性和不处理重复
  • 独特 - 使用的文件内容的哈希是我的最爱方法,因为它保证内容独特性,并节省您的硬盘空间,因为你只能有最多2个相同的文件(一个与原来的文件名和另一个哈希附加),示例代码:

(伪文本,以便下一行被格式化为代码。)

$token = '_' . md5_file($_FILES[$input]['tmp_name']); 

希望它能帮助! ;)

+1

确实很有帮助。特别是每个文件夹的文件限制。我真的很喜欢创建文件哈希的想法。 – PeeHaa 2011-05-02 23:08:25

+0

只是一个很好的答案! – 2015-08-13 13:38:38

3

没有这样的约定,但通常,名称是随机生成的,以使猜测不太可能。强烈建议不要使用文件名来清理文件,至少采用白名单方法,在该方法中,您除去白名单中的所有字符。关键是安全性,上传是一项危险的功能,如果处理不当,可能会很危险。

2

只是在内部自己做一些约定。例如,您可以将文件保存为userId_timestamp,并将原始文件名保存在某个数据库中。或者你只是把它做成userId_originalFilename或其他一些使它独一无二的东西组合。

0

您可以使用用户名和上传日期的某种组合吗?

1

在类似的情况下,我将信息保存在表格中(用户ID作为外键),用文件名前导零(即000345.jpg)格式化自动数字ID并将原始名称存储在表格中。

+0

当然这是对于'合理'的文件数量。如果没有,您可以使用一些更高级别的分组文件夹,如用户名或user_id。 – morgar 2011-05-02 23:15:55