3

我正在创建一个数据库应用程序(除其他外),它允许用户上传和下载文件。这些文件存储在文件服务器上,我已经使用 PHP 脚本设置了一个 Apache HTTP 服务器来处理(即上传和下载)文件。数据库只存储文件的链接,而不是文件本身。我的问题是:我应该如何组织文件服务器上的文件?

目前,我正在根据当前日期创建一个目录结构,并使用当前日期/时间(包括毫秒)的 MD5 哈希值加上一些随机字符(即我添加“salt”)重命名文件:

\\yyyy\mm\dd\debb40da158040e4f3b93f9576840c07

这个(上面)是存储在数据库中的链接(当然,我也将真实的文件名存储在数据库中,以便在用户下载文件时重命名文件——用户永远看不到实际的文件名)关联)。

我使用yyyy\mm\dd目录结构来避免性能问题(我被告知同一目录中的很多文件会减慢速度)并且我用唯一的字符串重命名文件以避免在用户上传具有相同名称的文件时发生冲突。

我想就在这种情况下处理文件存储的最佳方式获得其他意见。我已经看到一些开发人员保留文件名,但在文件信息表中附加(作为前缀)相应行的数据库 ID ---我看到了这种方法的一些优点,因为文件名是“人类可读的”并且如果数据库文件信息表被损坏或删除,您可以弄清楚这些文件是什么。

4

1 回答 1

3

使用时间戳(上传日期)作为第一级目录的结构怎么样,文件内容的 md5 哈希作为第二级(文件内容的哈希确保文件是唯一的/名称独立的),上传时间戳作为第三级(使您在不同时间上传同一文件的不同版本),并且文件的实际文件名位于第 4 级。e.g. <date timestamp>/<md5 of file contents>/<timestamp>/<filename>

这样,您的目录结构将包含以下信息:

  • 在特定日期上传的文件列表
  • 独立于文件名的唯一文件
  • 版本控制
  • 维护文件名而无需即时更改它

文件内容 md5 哈希的缺点是,如果您有非常大的文件,则生成时会产生轻微的开销。

进一步的想法

  • 如果这是一个有许多用户每天上传文件的系统并且肯定会为一年中的每一天创建 365 个目录,您可以将日期打破为以前的格式(yyyy/mm/dd 甚至只是 yyyy/date),尽管当您在目录中有大于 10k 的条目列表时性能会降低(并且在基于服务器的操作系统中大于 100k 到数百万),因此如果您在注意到任何降级之前应该给您大约 25-30 年只使用一个日期目录。

  • 我相信文件内容的哈希是保证文件名独立性的方法,虽然计算内容的 md5 会增加一点开销,但与上传时间相比,它是微不足道的。例如,根据连接速度,上传 100 mb 文件需要 x 时间,上传后您只需使用 md5sum 即时计算文件内容,这将增加几秒钟(100 mb 文件需要 5-6 ) 到用户将感知到的上传时间。

  • 您可以进一步使用文件内容的 md5(假设您也将其存储在数据库中)作为保护原始上传文件真实性的签名

  • 在当前场景的上下文中,您实际上不需要 dir 结构中的时间戳(+salt),除非您想要对文件进行版本控制或保证没有上传以不同名称命名的相同文件(否则您最终会在同一文件内容下具有不同的文件名 md5 命名为 dir 为给定的一天)。

  • 不知道为什么你会介意 md5 字符串的长度。它不会影响性能,并且 md5 非常普遍,并且很好地支持用于其他目的(例如验证文件)。但是,如果您真的想缩短长度,请查看http://en.wikipedia.org/wiki/List_of_hash_functions并选择一个 16 位或 8 位甚至 4 位的 crc 进行试验(同样取决于您的工作方式使用它,文件内容或文件名以及它们有多大)。

  • 最后,另一种选择是执行<group>/<user_id>/<filehash>/<timestamp>/<filename>where group will be user ids 1 to<acceptable number of entries in a dir>,比如 10000 或更少,但您可以通过在服务器上试验有多少条目会降低性能来发现这一点,并且当达到限制时,您有一个脚本会创建一个具有相同结构的新组。通过这种方式,您可以避免重复/相似的信息(日期、年份、月份、时间戳等),您可以自己控制可接受的限制,您可以让不同的用户上传相同的文件,您可以通过 filehash 来判断文件是否已被无论文件名如何上传,您都使用时间戳进行版本控制,并且在最后的目录中只有一个文件具有其原始(或指定)名称。如果您是 FaceBook 并拥有十亿用户,您可以拥有这种结构并跨不同服务器托管目录组集群。如果您有一个拥有 1000 个用户的小型网站,您甚至不需要群组位。

于 2012-10-15T21:27:54.230 回答