存储数据库中文件的链接

时间:2012-10-15 21:18:29

标签: database database-design fileserver file-organization

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

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

\\yyyy\mm\dd\debb40da158040e4f3b93f9576840c07

这(上面)是存储在数据库中的链接(当然,我还将真实文件名存储在数据库中,以便我可以在用户下载文件时重命名该文件---用户从不看到了实际的链接。)

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

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

1 个答案:

答案 0 :(得分:3)

如何使用时间戳(上传日期)作为第1级目录的结构,文件内容的md5哈希作为第2级(文件内容的哈希确保文件是唯一/名称无关的),上传时间戳为第3级(使您能够在不同时间上传相同文件的不同版本),以及具有第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的文件将需要一段时间来上传,具体取决于连接速度,上传后你只需使用md5sum即可计算文件内容,这将只需几秒钟(对于一个100 MB的文件,为5-6)到用户将感知它的上传时间。

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

  • 在本方案的上下文中,您实际上不需要dir结构中的时间戳(+ salt),除非您希望对文件进行版本控制或保证未上载相同的文件名(不同)否则你将在给定日期命名为dir的相同文件内容md5下使用不同的文件名。

  • 不确定为什么你会想到md5字符串的长度。它不会影响性能,并且md5非常普遍,并且也很好地支持用于其他目的(例如验证文件)。但如果你真的想减少长度,请查看http://en.wikipedia.org/wiki/List_of_hash_functions并选择16或8甚至4位crc进行试验(再次取决于你将如何使用它,文件内容或文件这些名称及其大小。)

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