我正在考虑开发我自己的基于 PHP 的画廊来存储大量图片,可能有数万张。
在数据库中,我将指向图像的 url,但问题是:我知道让它们都位于服务器的同一目录中是不切实际的,因为它会减慢爬网的访问速度,所以,你会怎么做全部存储?某种基于 jpeg/png 名称的树?
你会向我推荐什么分割图像的规则?
(它将专注于在cheapo dot coms 中使用,因此不可能与服务器发生冲突)
我正在考虑开发我自己的基于 PHP 的画廊来存储大量图片,可能有数万张。
在数据库中,我将指向图像的 url,但问题是:我知道让它们都位于服务器的同一目录中是不切实际的,因为它会减慢爬网的访问速度,所以,你会怎么做全部存储?某种基于 jpeg/png 名称的树?
你会向我推荐什么分割图像的规则?
(它将专注于在cheapo dot coms 中使用,因此不可能与服务器发生冲突)
我们过去也遇到过类似的问题。并找到了一个不错的解决方案:
我们已经体验过,使用指南,您会获得或多或少的统一划分。它就像一个魅力。
可能有助于生成唯一 ID 的链接:
几年前我在一个电子文档管理系统上工作,我们几乎按照 Gamecat 和 wic 的建议做了。
也就是说,为每个图像分配一个唯一的 ID,并使用它来导出图像文件的相对路径。我们使用了类似wic建议的MOD,但是我们允许每个级别1024个文件夹/文件,有3个级别,所以我们可以支持1G文件。
但是,我们从文件中删除了扩展名。数据库记录包含 MIME 类型,因此不需要扩展。
我不建议将完整的 URL 存储在数据库记录中,只存储图像 ID。如果您存储 URL,您将无法在不转换数据库的情况下移动或重组您的存储。相对 URL 可以,因为这样您至少可以移动图像存储库,但如果您只存储 ID 并派生 URL,您将获得更大的灵活性。
此外,我不建议允许从网络直接引用您的图像文件。相反,提供一个服务器端程序(例如,Java Servlet)的 URL,并在 URL 查询 ( http://url.com/GetImage?imageID=1234
) 中提供图像 ID。
servlet 可以使用该 ID 来查找 DB 记录、确定 MIME 类型、导出实际位置、检查安全限制、日志记录等。
我通常只使用数字数据库 id (auto_increment),然后使用模数 (%) 运算符来确定文件的放置位置。简单且可扩展。例如,可以像这样创建 id 为 12345 的图像的路径:
12345 % 100 = 45
12345 % 1000 = 345
结束于:
/home/joe/images/345/45/12345.png
或类似的东西。
如果您使用的是 Linux 和 ext3 以及文件系统,则必须注意目录中可以拥有的目录和文件的数量是有限的。dirs 的限制是 32000,因此您应该始终努力保持较低的 dirs 数量。
我知道将它们全部放在服务器中的同一目录中是不切实际的,因为它会减慢对爬网的访问。
这是一个假设。
我设计了一个系统,我们将数百万个文件平放在一个目录中,效果很好。它也是最容易编程的系统。大多数服务器文件系统都毫无问题地支持这一点(尽管您必须检查您使用的是哪一个)。
保存与 auto_increment id 关联的文件时,我使用类似以下的内容,它创建三个目录级别,每个级别由 1000 个目录组成,每个第三级目录中有 100 个文件。这支持约 1000 亿个文件。
如果 $id = 99532455444 那么以下返回 /995/324/554/44
function getFileDirectory($id) {
$level1 = ($id / 100000000) % 100000000;
$level2 = (($id - $level1 * 100000000) / 100000) % 100000;
$level3 = (($id - ($level1 * 100000000) - ($level2 * 100000)) / 100) % 1000;
$file = $id - (($level1 * 100000000) + ($level2 * 100000) + ($level3 * 100));
return '/' . sprintf("%03d", $level1)
. '/' . sprintf("%03d", $level2)
. '/' . sprintf("%03d", $level3)
. '/' . $file;
}
查看 XFS 文件系统。它支持无限数量的文件,Linux 支持它。 http://oss.sgi.com/projects/xfs/papers/xfs_usenix/index.html
您可以在表格中有一个 DateTime 列,然后将它们存储在以月、年甚至月、日、年命名的文件夹中,并将图像添加到表格中。
例子
这样,您最终的文件夹深度不会超过 3 个。
我目前正面临这个问题,而 Isaac 所写的内容让我对这个想法产生了兴趣。我的功能有点不同。
function _getFilePath($id) {
$id = sprintf("%06d", $id);
$level = array();
for($lvl = 3; $lvl >= 1; $lvl--)
$level[$lvl] = substr($id, (($lvl*2)-2), 2);
return implode('/', array_reverse($level)).'.jpg';
}
我的图片只有数千张,所以我最多只能有 999999 的限制,所以它会将其拆分为 99/99/99.jpg 或 43524 拆分为 04/35/24.jpg
使用文件系统的层次结构。使用 001/002/003/004.jpg 之类的东西来识别您的图像会非常有帮助。不过,分区是另一回事。可以是随机的、基于内容的、基于创建日期的等等。这真的取决于你的应用程序是什么。
您可以查看 Apple iPod 用于存储其多媒体内容的策略。有一层深度的文件夹和具有相同宽度标题的文件。我相信苹果公司的人投入了大量时间来测试他们的解决方案,因此它可能会给你带来一些立竿见影的好处。
如果您处理的图片是数码照片,您可以使用 EXIF 数据对它们进行排序,例如按拍摄日期。
您可以将图像作为 blob 存储在数据库中(对于 mssql为varbinary )。这样您就不必担心存储或目录结构。唯一的缺点是您不能轻松浏览文件,但无论如何这在平衡的目录树中都很难。