问题 文件夹结构用于存储数百万张图像?


我正在建立一个网站,正在查看数百万张照片上传很容易(每张图片上传3张缩略图),我需要找到存储所有这些图像的最佳方法。

我搜索并找到了存储为哈希的图像示例......例如......

如果我上传,coolparty.jpg,我的脚本会将其转换为Md5哈希导致..

dcehwd8y4fcf42wduasdha.jpg

并存储在 /dc/eh/wd/dcehwd8y4fcf42wduasdha.jpg 但对于3个缩略图,我不知道如何存储它们

质询..

  1. 这是存储这些图像的正确方法吗?

  2. 我如何存储缩略图?

  3. 在PHP中,使用上述方法存储这些图像的示例代码是什么?


13021
2017-09-04 04:30


起源

希望你有一个具有大量带宽的下降规范服务器。
如果您有两个用户上传名为的文件,会发生什么 coolparty.jpg?您是否需要将用户名作为文件名的一部分存储? - andrewsi
对于所有那些令人沮丧的数据库,因为它们“缓慢” - 没有数字来支持它,它只是热空气。是的,数据库可能很慢。文件系统也可能很慢。 (尝试在一个目录中放置一百万甚至50,000个图像,并观察文件访问时间猛增。)至于数据库, 这是一个实际的研究 主张使用数据库。另外,请参阅 这个帖子 在网站管理员。 - Ted Hopp
此实现可能很有用:github.com/acrobit/AcroFS - Ghominejad


答案:


我如何使用文件夹结构:

  • 我正在上传照片,并像你说的那样移动照片:

    $image = md5_file($_FILES['image']['tmp_name']);
    // you can add a random number to the file name just to make sure your images will be "unique"
    $image = md5(mt_rand().$image);
    $folder = $image[0]."/".$image[1]."/".$image[2]."/";
    
    // IMAGES_PATH is a constant stored in my global config
    define('IMAGES_PATH', '/path/to/my/images/');
    // coolparty = f3d40fc20a86e4bf8ab717a6166a02d4
    $folder = IMAGES_PATH.$folder.'f3d40fc20a86e4bf8ab717a6166a02d4.jpg';
    // thumbnail, I just append the t_ before image name
    $folder = IMAGES_PATH.$folder.'t_f3d40fc20a86e4bf8ab717a6166a02d4.jpg';
    // move_uploaded_file(), with thumbnail after process
    // also make sure you create the folders in mkdir() before you move them
    
  • 我相信是基本的方式,当然你可以将文件夹结构更改为更深的文件夹,就像你说的那样,如果你有数百万张图片就会有2个字符。


9
2017-09-04 04:39



谢谢!我试试这个 - Kenny
记得检查目录是否存在(is_directory),可能检查权限(is_writable),使用mkdir和chmod创建缺少的目录等。我还建议你chmod上传的文件,以确保你可以使用ftp进行操作(如果Apache / IIS / Tomcat和FTP作为不同的用户运行,因为它们通常是)。你需要担心这个答案中有很多缺失! - Robbie
@mihai你说,“是的,这是最好的方式,除非你把它们存储在云服务中。”我在云端服务Softlayer,如果你在使用云服务,为什么这不是最好的? - Kenny
我在softlayer.com的服务器上,所以不,我不使用自己的服务器 - Kenny
对不起,我想说一些数据存储服务.. - Mihai Iorga


您使用这样的方法的原因只是减少每个目录(inode)的文件总数。

使用您描述的方法(3级深度),您每个目录甚至不可能达到数百个图像,因为您将拥有近17MM的最大目录数。 16 ** 6。

至于你的问题。

  1. 是的,这是存储它们的好方法。
  2. 我会这样做的方式

    /aa/bb/cc/aabbccdddddddddddddd_thumb.jpg
    /aa/bb/cc/aabbccdddddddddddddd_large.jpg
    /aa/bb/cc/aabbccdddddddddddddd_full.jpg

    或类似的

  3. 就如何实际存储图像而言,网上有很多例子。你有更具体的问题吗?

7
2017-09-04 04:41





如果您正在谈论数百万张照片,我建议您将这些照片发送给第三方,例如Amazon Web Services,更具体地说是针对此Amazon S3。文件数量没有限制,假设您不需要实际列出文件,则根本不需要将它们分成目录(如果您确实需要列出,则可以使用不同的分隔符和前缀 - http://docs.amazonwebservices.com/AmazonS3/latest/dev/ListingKeysHierarchy.html)。而你的托管/重建成本可能会低于自己 - 并且他们会得到备份。

更具体地回答,是的,按子目录拆分;使用您的结构,您可以删除文件名的前5个字符,因为您已经在目录名称中使用了它。

和aquinas建议的拇指一样,只是在文件名中添加了_thumb1等。或者存储在单独的文件夹中。


2
2017-09-04 04:41



好吧,关于S3服务,截至目前我不会这样做,但如果我坚持这个当前的方法我考虑,如果我决定将所有文件移动到S3,是否很容易将所有文件传输到那里? - Kenny
编写脚本以将所有文件从文件系统移动到s3会非常容易。你甚至可以维护你的目录结构。 - sberry
+1提及替代方案。 s3是一项非常好的服务。 - sberry
是的 - 一旦项目启动并运行,您可以将它们全部移动。但是关于设置Amazon S3的最复杂(也很烦人)的事情是注册并提供信用卡详细信息:)。实际上传是几行代码 - 非常非常简单。你会花更长时间担心mkdir和权限以及所有爵士乐在本地处理。做一些成本计算,如果项目真的会那么大,那就这样开始,省去麻烦。 - Robbie


1)这是你能回答的问题。通常,我更喜欢将图像存储在数据库中,因此您可以拥有一个一致的备份,但是YMMV。

2)怎么样? /dc/eh/wd/dcehwd8y4fcf42wduasdha_thumb1.jpg,/dc/eh/wd/dcehwd8y4fcf42wduasdha_thumb2.jpg和/dc/eh/wd/dcehwd8y4fcf42wduasdha_thumb3.jpg怎么样

3)???您是否在询问如何将文件写入文件系统或...?


-3
2017-09-04 04:34



从数据库中提取图像并显示它们比使用文件访问要慢。 - chhameed
考虑到有多少图像,将它们存储在传统的sql数据库中并不是一个好方法。像Cassandra,Redis,Riak等的无sql db更容易接受,但文件系统应该是第一个考虑因素。 - sberry
@Hameed - 我不认为像这样的一揽子陈述是合理的。涉及的变量太多了。 (数据库缓存;文件系统争用;分布式文件系统;等等)如果需要任何类型的锁定,数据库可能比家庭酿造的基于文件的锁定系统更加健壮和灵活。 - Ted Hopp
@Hameed,正如我所说,你的里程可能会有所不同。我没有注意到这个问题被标记为MySQL。在SQL Server中,有一个FileStream数据类型: blogs.msdn.com/b/manisblog/archive/2007/10/21/... 就是出于这个目的。 - aquinas
另外,在MySQL中,你能创建一个允许你从文件系统中删除文件的触发器(模仿级联删除)吗?这可能是可能的,我只是不知道如何脱离我的头脑。 - aquinas


改善答案。

对于数百万的图像,同样如此,使用数据库将减慢该过程是正确的

最好的选择是使用“服务器文件系统”来存储图像,并使用.htaccess来增加安全性。

或者你可以使用网络服务。很多服务器都提供Images Api来上传,显示。 你也可以选择这个选项。例如亚马逊


-3
2017-09-04 04:41



在数据库中存储数百万个图像并不是正确的方法恕我直言。 - sberry
从数据库中提取图像并显示它们比使用文件访问要慢。 - chhameed
并且肯定比文件系统慢
好的,谢谢你纠正我:) - shail
@Hameed - 你有证据支持这种说法吗? - Ted Hopp