【问题标题】:Naming convention uploaded files [closed]命名约定上传的文件[关闭]
【发布时间】:2011-05-15 10:25:07
【问题描述】:

在我的网站上,我让用户上传文件。

如果文件有效并已上传,则将其移至文件夹(使用 PHP)。

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

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

是否有类似于默认命名约定的方式让用户上传具有相同文件名的文件?

【问题讨论】:

    标签: php file-upload naming-conventions


    【解决方案1】:

    没有标准约定,但有几个最佳实践:


    将您的文件组织到(用户和/或日期)感知文件夹中

    类似:

    /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() - 每秒确保唯一性,但处理重复文件很糟糕
    • 随机 - 不是一个好主意,因为它不能确保唯一性并且不能处理重复项
    • unique - 使用文件的哈希 contents 是我最喜欢的方法,因为它保证 content 唯一性并为您节省 HD 空间,因为您最多只有 2 个相同的文件(一个带有原始文件名,另一个带有哈希附加),示例代码:

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

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

    希望对您有所帮助! ;)

    【讨论】:

    • 确实很有帮助。特别是每个文件夹的文件限制。我真的很喜欢创建文件哈希的想法。
    • 只是一个很好的答案!
    【解决方案2】:

    没有这样的约定,但通常,名称是随机生成的,以减少猜测的可能性。强烈建议不要在不清理的情况下允许文件名,至少采取一种白名单方法,在这种方法中删除除白名单中的字符之外的所有字符。关键是安全性,上传是一项有风险的功能,如果处理不当可能会很危险。

    【讨论】:

      【解决方案3】:

      自己在内部制定一些约定。例如,您可以将文件作为userId_timestamp 存储在文件夹中,并将原始文件名保留在某个数据库中。或者,您只需将其设为 userId_originalFilename 或其他使其独一无二的事物组合。

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • 当然,这是针对“合理”数量的文件。如果没有,您可以使用一些更高级别的分组文件夹,例如 username 或 user_id。
        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-09-08
          • 1970-01-01
          • 1970-01-01
          • 2015-04-02
          • 2010-10-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多