我应该将上传的文件名存储在数据库中吗?
Should I store uploaded filename in database?
我有一个数据库 table,主键是自动增量 ID。
对于此 table 的每条记录,我最多可以有 3 个文件,这些文件可以公开使用,因此随机文件名生成不是强制性的,这些文件是可选的。
我想我有 2 个可能的解决方案:
将随机生成的文件名存储在 3 个可为空的 varchar 列中,并将所有文件存储在同一位置:
- 列:一个 |乙 | c
- uploads/f6se54fse654.jpg
不存储文件名,而是将它们放在特定的文件夹中,并将它们命名为与主键值相同的名称:
- uploads/a/1.jpg
- uploads/b/1.jpg
- uploads/c/1.jpg
通过最后一个解决方案,我知道 uploads/a/1.jpg
属于 ID 1
的记录,并且是 a
类型的文件。但是我必须检查文件是否存在,因为文件是可选的。
你认为这一切有好的做法吗?或者也许有更好的方法?
如果您正在谈论的文件旨在供用户显示或下载(无论是针对访问者还是针对经过身份验证的用户,是否按角色(ACL)过滤),重要的是要确保(恕我直言)用户将无法猜测除了已发送给他的有关资源的内容以外的其他信息。没有完美的解决方案可以无一例外地适用于所有情况,所以让我们举个例子来给你更多的解释。
为了增强敏感数据的安全性和完全不透明性,例如对于 uploads/users/7/invoices/3.pdf
的特定情况,我认为确保绝对没有人可以猜到文件的数量是明智的可能与用户或任何其他实体相关联(否则,在此示例中,我们可以想象可能存在其他可访问文件 - 1.pdf 和 2.pdf)。通过设计,我们通常希望在明确定义的特定情况和上下文中授予对文件的访问权限。但是,对于旨在供所有人查看的图像文件(例如个人资料照片),情况可能并非如此。这就是为什么上下文在某种程度上很重要。
如果您选择保留自动递增的标识符作为名称来引用您的文件,这也可以提供有关存储在数据库中的数据大小的信息(/uploads/invoices/128.pdf
告知您可能已经127 张发票),并可能激励不道德的人尝试获取不应从定义的上下文中获取的资源。如果您选择使用某种唯一生成的标识符 (GUID),这种情况可能不太明显。
我建议您阅读与我所指内容相关的 this article concerning the generation of (G)/(U)UIDs (a 128-bit hexadecimal numbers) to be stored in your database for each uploaded or created file. If you use MySQL in its latest version it is even possible to host this identifier in a binary (16)
type which offers an automatic conversion to UUID, I let you read this interesting topic。它可能会将此输出为 /uploads/invoices/b0016303-8e4f-487a-8c30-5dddf1ebf7e9.pdf
,只要您确保生成的标识符是唯一的哈希值,这会好很多。
在这里谈性能问题对我来说似乎没有用,因为今天有很多缓存文件或路径和url的方法,这避免了在很多调用资源的情况下每次都必须发出请求(通常按大数据案例中的受欢迎程度排序)。
最后但同样重要的是,许多网络和移动平台应用程序(我想到了 Slack、Discord、Facebook、Twitter...),它们每天存储大量媒体文件,这些文件通常与帐户用户相关联,既public 和机密文件和信息,为它们中的每一个生成一个唯一的哈希值。
Twitter 正在使用自己的唯一标识符字符串(64 位 BIGINT
)生成器,称为 Twitter Snowflake,您可能也会对它感兴趣。它基于 UNIX 纪元值,根据定义,该值在每个毫秒节拍都是唯一的。
没有一个可以适用于所有情况的全局和完美的解决方案,但我希望这对您有所帮助,因为您可能想要更深入地了解它并找到每个上下文的 "best solution"和您将存储的实体和 link 文件。
我有一个数据库 table,主键是自动增量 ID。
对于此 table 的每条记录,我最多可以有 3 个文件,这些文件可以公开使用,因此随机文件名生成不是强制性的,这些文件是可选的。
我想我有 2 个可能的解决方案:
将随机生成的文件名存储在 3 个可为空的 varchar 列中,并将所有文件存储在同一位置:
- 列:一个 |乙 | c
- uploads/f6se54fse654.jpg
不存储文件名,而是将它们放在特定的文件夹中,并将它们命名为与主键值相同的名称:
- uploads/a/1.jpg
- uploads/b/1.jpg
- uploads/c/1.jpg
通过最后一个解决方案,我知道 uploads/a/1.jpg
属于 ID 1
的记录,并且是 a
类型的文件。但是我必须检查文件是否存在,因为文件是可选的。
你认为这一切有好的做法吗?或者也许有更好的方法?
如果您正在谈论的文件旨在供用户显示或下载(无论是针对访问者还是针对经过身份验证的用户,是否按角色(ACL)过滤),重要的是要确保(恕我直言)用户将无法猜测除了已发送给他的有关资源的内容以外的其他信息。没有完美的解决方案可以无一例外地适用于所有情况,所以让我们举个例子来给你更多的解释。
为了增强敏感数据的安全性和完全不透明性,例如对于 uploads/users/7/invoices/3.pdf
的特定情况,我认为确保绝对没有人可以猜到文件的数量是明智的可能与用户或任何其他实体相关联(否则,在此示例中,我们可以想象可能存在其他可访问文件 - 1.pdf 和 2.pdf)。通过设计,我们通常希望在明确定义的特定情况和上下文中授予对文件的访问权限。但是,对于旨在供所有人查看的图像文件(例如个人资料照片),情况可能并非如此。这就是为什么上下文在某种程度上很重要。
如果您选择保留自动递增的标识符作为名称来引用您的文件,这也可以提供有关存储在数据库中的数据大小的信息(/uploads/invoices/128.pdf
告知您可能已经127 张发票),并可能激励不道德的人尝试获取不应从定义的上下文中获取的资源。如果您选择使用某种唯一生成的标识符 (GUID),这种情况可能不太明显。
我建议您阅读与我所指内容相关的 this article concerning the generation of (G)/(U)UIDs (a 128-bit hexadecimal numbers) to be stored in your database for each uploaded or created file. If you use MySQL in its latest version it is even possible to host this identifier in a binary (16)
type which offers an automatic conversion to UUID, I let you read this interesting topic。它可能会将此输出为 /uploads/invoices/b0016303-8e4f-487a-8c30-5dddf1ebf7e9.pdf
,只要您确保生成的标识符是唯一的哈希值,这会好很多。
在这里谈性能问题对我来说似乎没有用,因为今天有很多缓存文件或路径和url的方法,这避免了在很多调用资源的情况下每次都必须发出请求(通常按大数据案例中的受欢迎程度排序)。
最后但同样重要的是,许多网络和移动平台应用程序(我想到了 Slack、Discord、Facebook、Twitter...),它们每天存储大量媒体文件,这些文件通常与帐户用户相关联,既public 和机密文件和信息,为它们中的每一个生成一个唯一的哈希值。
Twitter 正在使用自己的唯一标识符字符串(64 位 BIGINT
)生成器,称为 Twitter Snowflake,您可能也会对它感兴趣。它基于 UNIX 纪元值,根据定义,该值在每个毫秒节拍都是唯一的。
没有一个可以适用于所有情况的全局和完美的解决方案,但我希望这对您有所帮助,因为您可能想要更深入地了解它并找到每个上下文的 "best solution"和您将存储的实体和 link 文件。