存储大量图像

时间:2009-01-15 10:57:43

标签: image tree filesystems

我正在考虑开发自己的基于PHP的图库来存储大量图片,可能只有数万张。

在数据库中,我将指向图像的网址,但问题是:我知道让所有这些网站都位于服务器中的同一目录是不切实际的,因为它会减慢对爬网的访问速度,因此,你会如何存储所有这些?某种基于jpeg / png名称的树?

你会推荐我对图像进行分区的规则是什么?

(它将专注于使用cheapo dot coms,因此不可能使用服务器进行修改)

12 个答案:

答案 0 :(得分:46)

过去我们遇到过类似的问题。并找到了一个很好的解决方案:

  • 为每张图片添加一个独特的指南。
  • 为每个图像创建一个数据库记录,其中包含子图像的名称,位置,guid和可能的位置(缩略图,缩小尺寸等)。
  • 使用guid的第一个(一个或两个)字符来确定顶层文件夹。
  • 如果文件夹文件太多,请再次拆分。更新参考文献,您就可以开始了。
  • 如果文件数和访问次数过多,您可以将文件夹分布在不同的文件服务器上。

我们经历过使用guids,你会得到一个或多或少的统一分区。它就像一个魅力。

可能有助于生成唯一ID的链接:

答案 1 :(得分:11)

几年前我参与了一个电子文档管理系统,我们做了很多Gamecat和wic的建议。

即,为每个图像分配唯一的ID,并使用它来导出图像文件的相对路径。我们使用类似于wic建议的MOD,但我们在每个级别允许1024个文件夹/文件,有3个级别,所以我们可以支持1G文件。

然而,我们从文件中删除了扩展名。 DB记录包含MIME类型,因此不需要扩展名。

我不建议将完整的URL存储在数据库记录中,只存储图像ID。如果存储URL,则无法在不转换数据库的情况下移动或重构存储。相对URL是可以的,因为您至少可以移动图像存储库,但如果您只存储ID并派生URL,您将获得更大的灵活性。

此外,我不建议允许从网络直接引用您的图像文件。相反,提供服务器端程序(例如,Java Servlet)的URL,并在URL查询(http://url.com/GetImage?imageID=1234)中提供图像ID。

servlet可以使用该ID来查找数据库记录,确定MIME类型,派生实际位置,检查安全限制,记录等。

答案 2 :(得分:8)

我通常只使用数值数据库id(auto_increment),然后使用modulu(%)运算符来确定放置文件的位置。简单且可扩展。例如,id为12345的图像路径可以这样创建:

12345 % 100 = 45
12345 % 1000 = 345

结束于:

/home/joe/images/345/45/12345.png

或类似的东西。

如果您使用的是Linux和ext3以及文件系统,则必须注意目录中可以包含的目录和文件数量有限制。 dirs的限制为32000,所以你应该始终努力保持低位数。

答案 3 :(得分:7)

  

我知道将所有这些目录放在服务器的同一目录中是不切实际的,因为它会减慢对爬网的访问速度。

这是一个假设。

我设计的系统中有数百万个文件存放在一个目录中,并且效果很好。它也是最容易编程的系统。大多数服务器文件系统都支持这一点而没有问题(尽管你必须检查你正在使用哪一个)。

http://www.databasesandlife.com/flat-directories/

答案 4 :(得分:5)

当保存与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;
}

答案 5 :(得分:2)

查看XFS Filesystem。它支持无限数量的文件,Linux支持它。 http://oss.sgi.com/projects/xfs/papers/xfs_usenix/index.html

答案 6 :(得分:1)

你可以在表格中有一个DateTime列,然后将它们存储在以月,年甚至月,日,年为单位命名的文件夹中,这些文件将添加到表中。

实施例

  1. 2009
  2. -01
  3. - 01
  4. - 02
  5. - 03
  6. - 31
  7. 这样你最终不会超过3个文件夹。

答案 7 :(得分:1)

我目前正面临这个问题,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

答案 8 :(得分:0)

使用文件系统的层次结构。使用像001/002/003 / 004.jpg这样的ID来识别您的图像会非常有帮助。但是,分区是一个不同的故事。可以是随机的,基于内容的,基于创建日期等。真正取决于您的应用程序是什么。

答案 9 :(得分:0)

您可以查看Apple iPod用于存储其多媒体内容的策略。有一个深度级别的文件夹和具有相同宽度标题的文件。我相信苹果公司在测试他们的解决方案上投入了大量时间,因此它可能为您带来一些直接利益。

答案 10 :(得分:0)

如果您处理的图片是数码照片,则可以使用EXIF数据对其进行排序,例如按拍摄日期进行排序。

答案 11 :(得分:0)

您可以将数据作为blobs存储在数据库中(varbinary用于mssql)。这样您就不必担心存储或目录结构。唯一的缺点是您无法轻松浏览文件,但无论如何,这在平衡目录树中都很难。