有效地将用户上传的图像存储在文件系统上

时间:2011-08-26 09:55:37

标签: php mysql image

方案

用户可以发布项目并在帖子中包含最多5个图像,上传的每个图像都需要重新采样和调整大小 - 总共创建4个额外图像。这意味着,如果用户上传了5张图像,最终会有25张图像存储起来。

假设

  • 图片已经 正确 ,并且它们是有效的图片文件
  • 系统必须进行缩放(假设第一个实例为1000个帖子,因此最多5000个图像)
  • 每个图像都根据db post条目的auto_incremenet id重命名,并包含相关后缀,即12345_1_1.jpg 12345_2_1.jpg - 所以重复没有问题
  • 图像不是敏感的,所以直接访问它们没有问题(尽管目录列表将被禁用)

可能的方法

  • 鉴于ID是唯一的,我们可以将它们放入一个文件夹中(在某一点之后无效)。
  • 可以为每个帖子创建一个文件夹并将所有图像放入其中,因此ROOT / images / 12345(同样会以多个文件夹结束)
  • 可以根据日期进行图像存储,即每天创建一个新文件夹,并将日期图像存储在那里。
  • 可以根据调整大小的类型存储图像,即所有原始文件可以存储在一个文件夹images / orig所有缩略图中的图像/拇指(我认为Gumtree使用这样的方法)。
  • 在创建另一个文件夹之前,可以允许将X个文件存储在一个文件夹中。

任何人都有关于存储图像的最佳实践/方法的经验吗?

注意:我预先有人会提到S3 - 让我们假设我们想暂时保留本地图像。

感谢您寻找

3 个答案:

答案 0 :(得分:12)

我们有大量生产这样的系统,迄今为止有30,000多个文件和20多GB ......

   Column    |            Type             |                        Modifiers                         
-------------+-----------------------------+----------------------------------------------------------
 File_ID     | integer                     | not null default nextval('"ACRM"."File_pseq"'::regclass)
 CreateDate  | timestamp(6) with time zone | not null default now()
 FileName    | character varying(255)      | not null default NULL::character varying
 ContentType | character varying(128)      | not null default NULL::character varying
 Size        | integer                     | not null
 Hash        | character varying(40)       | not null
Indexes:
    "File_pkey" PRIMARY KEY, btree ("File_ID")

文件只存储在一个目录中,整数File_ID作为文件名。我们超过30,000没有问题。我测试得更高没有问题。

这是使用RHEL 5 x86_64和ext3作为文件系统。

我会这样做吗?不,请允许我分享一些关于重新设计的想法。

  1. 数据库仍然是文件信息的“主要来源”。

  2. 每个文件都是sha1()散列并存储在基于该散列的文件系统层次结构中: /FileData/ab/cd/abcd4548293827394723984723432987.jpg

  3. 数据库在每个文件上存储元信息方面要聪明一些。这将是一个三表系统:

    File:存储名称,日期,IP,所有者和指向Blob(sha1)的指针等信息 File_Meta:在文件上存储键/值对,具体取决于文件类型。这可能包括Image_Width等信息。
    Blob:存储对sha1的引用及其大小。

  4. 该系统通过存储散列引用的数据来重复删除文件内容(多个文件可以引用相同的文件数据)。使用rsync备份同步文件数据库非常容易。

    此外,将删除包含大量文件的给定目录的限制。

    文件扩展名将存储为唯一文件哈希的一部分。例如,如果空文件的哈希是abcd8765 ...空.txt文件和空.php文件将引用相同的哈希。相反,他们应该引用abcd8765.phpabcd8765.txt。为什么呢?

    Apache等可以配置为根据文件扩展名自动选择内容类型和缓存规则。使用有效名称和反映文件内容的扩展名存储文件非常重要。

    你知道,这个系统可以通过委托通过nginx传递文件来提高性能。见http://wiki.nginx.org/XSendfile

    我希望这在某种程度上有所帮助。小心。

答案 1 :(得分:1)

我会将所有图像存储在一个文件夹中 - 然后数据库会跟踪文件名 - 保持简单

答案 2 :(得分:0)

首先,我建议为图像创建一个表。这是一行/图像文件表:

| id  | filename | type     | storage |
---------------------------------------
| 123 | 123.png  | original | store1  |
  • id auto incremental int或同样独特的东西。
  • filename文件base name。这允许您移动文件并只更新代码。文件名可以是{file_id}.{extension}
  • type是图片的类型:originalthumbnailresized,等等。也可以是尺寸:100x100500xx500(其中500x将是无限高度,x500将是无限宽度)。这只是一些例子。
  • storage将是文件所在的标识符,这可以是目录。假设您将图像存储在post_images中,文件名为123.png,存储空间为store1,则路径为post_images/store1/123.png

我自己还没试过,但我在同一目录中存储10k +文件的网络应用程序存在问题。