文件主机的目录结构

3
我搭建了一个简单的文件托管服务,为文件分配唯一的id并将其存储在一个目录中。我被告知这将会在未来引起问题,因此想知道有哪些事情需要注意,以确保它能够顺利地运行到未来及更远的未来。
此外,通过发送头信息和readfile()强制下载是否存在性能问题?保留文件名并允许直接下载而不是使用脚本是否更好?
谢谢。
5个回答

6
您听说过因为将数千个文件堆积在同一目录下而导致性能下降的问题。为了解决这个问题,请不要直接将文件存储在一个目录下,而是尝试将它们分散到子目录(桶)中。为了实现这一点,查看您要存储的文件的ID(假设为19873),并将其存储在“uploads/73/98/19873_filename.ext”下,其中73是“ID%100”,98是“(ID / 100)%100”等。以上保证您最多只有100个子目录在uploads下,并且最多只有100个进一步的子目录在uploads/*下。这将显着减少每个目录中叶子节点的文件数量。两级子目录是很典型的,也是在广度和深度上的一个很好的平衡。您还可以选择使用更大或更小的值(10、1000)来代替100。对于10万到500万个文件,带有模数100的两个级别是理想的。使用相同的技术计算需要检索的文件的ID以及文件系统上文件的完整路径。

3
此外,通过发送标头信息和readfile()强制下载是否存在性能问题?
是的,如果你做得不好。一个好的文件下载脚本应该:
- 流式传输长文件以避免填充内存 - 支持ETags和Last-Modified请求/响应标头以确保缓存继续工作 - 制定合理的Expires/Cache-Control设置
它仍然不会像Web服务器那样快(通常是用C语言编写的,并且对于提供文件进行了大量优化,甚至可能使用操作系统内核功能),但它会好得多。
保留文件名并允许用户直接下载比使用脚本更好吗?
是的,它的性能会更好,但正确处理安全性是一项挑战。请参见这里进行讨论。
一种折衷方案是使用重写,使URL看起来像:
hxxp://www.example.com/files/1234/Lovely_long_filename_that_can_contain_any_Unicode_character.zip

但它会在内部重定向到:
hxxp://www.example.com/realfiles/1234.dat

并由Web服务器(快速)提供服务。


3

首先,你的第一个问题取决于所使用的文件系统类型。在回答时,我会假设你使用的是未经任何日志优化的ext3。

首先,当文件数量超过系统ARG_MAX时,一个位置上有太多文件可能会导致问题。换句话说,rm -rf * 命令将退出并抱怨参数太多。你可以考虑根据其唯一名称最左边的字节的值适当地将文件停放在A-Z / a-z目录中。

此外,尽量避免在短时间内打开所有这些文件的进程...像“updatedb”这样的cron一旦开始真正填充就会出现问题。同样,尽量将这些目录排除在类似“find”之类的命令范围之外。

这引出了另一个潜在的问题,即缓冲区。这些文件有多频繁地被访问?如果在给定目录中有300个文件,是否所有文件每30分钟至少被访问一次?如果是这样,你可能需要调高/proc/sys/vfs_cache_pressure设置,以便Linux回收更多内存并使其可用于PHP/Apache/Etc。

最后,关于readfile…我建议只使用直接下载链接。这避免了PHP在下载过程中需要保持活动状态的情况。


1
如果你可能有成千上万的文件,你应该将它们分散在许多子目录中。
我建议保留原始文件名,尽管你可能需要修改它以确保唯一性。这在诊断问题时非常有帮助。

0
在我看来,我建议使用一些脚本来控制滥用。此外,我建议保留文件名,除非您的脚本将在数据库中创建一个与其原始状态相关的索引。您还可以尝试使用一些重写魔法的脚本,这样可以通过不向最终用户公开(您的唯一ID)后面的真实名称来带来另一层安全性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接