我应该将上传的文件名存储在数据库中吗?

Mar*_*arc 4 database database-design file-upload directory-structure file-storage

我有一个以自动增量 ID 作为主键的数据库表。

对于该表的每条记录,我最多可以有 3 个文件,这些文件可以公开,因此随机文件名生成不是强制性的,并且这些文件是可选的。

我想我有两种可能的解决方案:

  • 将随机生成的文件名存储在 3 个可为空的 varchar 列中,并将所有文件存储在同一位置:

    • 列:a | 乙| C
    • 上传/f6se54fse654.jpg
  • 不要存储文件名,而是将它们放在特定的文件夹中,并以与主键值相同的名称命名:

    • 上传/a/1.jpg
    • 上传/b/1.jpg
    • 上传/c/1.jpg

通过最后一个解决方案,我知道uploads/a/1.jpg属于 记录ID 1,并且是类型为 的文件a。但我必须检查该文件是否存在,因为这些文件是可选的。

您认为这一切有什么好的做法吗?或者也许有更好的方法?

Sen*_*nse 5

如果您正在谈论的文件旨在由用户显示或下载(无论是对于访问者还是经过身份验证的用户,是否按角色(ACL)过滤),重要的是要确保(恕我直言)用户将无法猜测除了已发送给他的相关资源的内容之外的其他信息。没有一个完美的解决方案可以无一例外地适用于所有情况,所以让我们举一个例子来给你更多的解释。

为了增强敏感数据的安全性和完全不透明性,例如对于 的具体情况uploads/users/7/invoices/3.pdf,我认为明智的做法是确保绝对没有人可以猜测与用户或任何其他实体潜在关联的文件数量(否则,在此示例中,我们可以想象可能存在其他可访问的文件 - 1.pdf 和 2.pdf)。根据设计,我们通常希望在明确定义的特定情况和上下文中授予对文件的访问权限。然而,对于每个人都可以看到的图像文件(例如个人资料照片)来说,情况可能并非如此。这就是为什么上下文在某种程度上很重要。

如果您选择保留自动递增标识符作为名称来引用您的文件,这还可以提供有关数据库中存储的数据大小的信息(/uploads/invoices/128.pdf通知您的服务器上可能已经有 127 张发票),并可能激发不道德的行为人们尝试访问永远不应该从定义的上下文中获取的资源。如果您选择使用某种唯一生成的标识符 (GUID),这种情况可能不太明显。

我建议您阅读这篇关于生成 (G)/(U)UID(128 位十六进制数字)的文章,这些 UID 会存储在每个上传或创建的文件的数据库中。如果您使用 MySQL 的最新版本,甚至可以将该标识符托管在binary (16)提供自动转换为 UUID 的类型中,我让您阅读与我所提到的内容相关的这个有趣的主题。/uploads/invoices/b0016303-8e4f-487a-8c30-5dddf1ebf7e9.pdf只要您确保生成的标识符是唯一的哈希值,它可能会输出这样更好的结果。

对我来说,在这里谈论性能问题似乎没有用,因为现在有很多缓存文件或路径和 url 的方法,这避免了在许多调用资源的情况下每次都必须发出请求(通常按其资源排序)大数据案例中的受欢迎程度排名)。

最后但并非最不重要的一点是,许多网络和移动平台应用程序(我想到 Slack、Discord、Facebook、Twitter...)每天都会存储大量媒体文件,这些文件通常与帐户用户相关联,包括公共文件和机密文件,以及信息,为每个信息生成唯一的哈希值。

Twitter 正在使用自己的唯一标识符字符串(64 位BIGINT)生成器,称为Twitter Snowflake,您可能也会有兴趣阅读。它基于 UNIX 纪元值,根据定义,该值在每个毫秒周期都是唯一的。

没有一个可以应用于所有情况的全局且完美的解决方案,但我希望这会对您有所帮助,因为您可能想更深入地了解这一点,并为您将存储的每个上下文和实体找到“最佳解决方案”和链接文件。