PHP在MySQL中存储图像与否?

时间:2009-02-09 11:33:16

标签: php mysql image

我已经在PHP中构建了一个小型Web应用程序,用户必须首先登录。一旦登录,我打算在他们的“个人资料”中显示一个小缩略图。

我必须确保图像低于特定尺寸以节省空间,或确保它是特定分辨率,或两者兼而有之,或者甚至可能使用像magick这样的尺寸来缩小它。
不知道最好的方法是什么,欢迎任何想法。

此外,我一直试图解决是否最好将图像存储在MySQL的users表中作为blob,或者可能是具有唯一ID的单独images表,以及只需将相应的图像ID存储在users表中,或者只是将上传的文件保存在服务器上(也可以通过上传页面)并将文件保存为theUsersUniqueUsername.jpg。 最佳选择?

我在这里找到了一个关于将图像保存到mysql的教程: http://www.phpriot.com/articles/images-in-mysql

我只是一个业余爱好程序员,之前从未做过这样的事情,所以非常感谢示例和/或很多细节。

16 个答案:

答案 0 :(得分:40)

总是依赖于上下文,但通常,我将文件系统上的用户图像存储在名为/content/user/{user_id}.jpg的文件夹中,并尝试尽可能少地打扰数据库。

答案 1 :(得分:23)

我建议将图像存储为文件,然后在数据库中包含文件URI。如果将所有图像存储在数据库中,则可能会在以后进行缩放时遇到一些问题。

同时查看this answer

  

对于速度和大小,Microsoft对SQL Server的建议曾经是将数据存储在文件系统中,并在数据库中包含链接。我认为他们已经稍微软化了他们的偏好,但我仍然认为这对于大小来说肯定是个更好的主意,因为它不会占用数据库中的空间。

答案 2 :(得分:17)

使用BLOB的开销远远低于大多数人认为的开销,特别是如果你设置正确的话。如果您使用单独的服务器运行数据库来存储二进制文件,那么您实际上根本不使用文件系统并避免文件系统的任何开销

除非你自己拥有几台服务器,否则说最简单/最好的方法是将它们存储在文件系统中

  • 不要将文件的绝对URL存储在数据库中,只能存储唯一的部分(可能还有一两个文件夹),例如: 2009/uniqueImageName.jpguniqueImageName.jpg。 然后在您的页面中只需将主机和其他文件夹添加到前面,这样您就可以灵活地移动图像 - 所有您需要更改的内容都是PHP / ASP.NET页面中的一行或两行。

  • 没有必要在文档根目录外存储以确保安全性 - 带有DENY FROM ALL的.htaccess文件将起作用并提供更大的灵活性

  • 为了安全起见,不需要“分流”图像,只需要getImage.php页面或其他内容,然后不要在src image中插入实际网址使用getImage.php?file=uniqueImageName.jpg之类的东西。 然后getImage.php文件可以检查用户是否已获得授权并抓取图像(或不是)。

  • 在存储时使用保证唯一的名称(最好是整数即主键),某些文件系统(即Windows)不区分大小写,因此JoeBloggs.jpg和{{1}对于数据库是唯一的,但对于文件系统则不是,因此会覆盖另一个。

  • 为图像使用单独的表,并将图像的主键存储在users表中。如果您想要在未来添加更多字段或进行更改,那将更容易 - 这也是一种很好的做法。

如果您担心搜索引擎优化等问题,请在上传时将图像的原始文件名存储在其他字段中,然后您可以在输出中使用它(例如joebloggs.jpg标记)。 / p>

答案 3 :(得分:16)

挑战传统智慧!

当然它依赖于上下文,但是我有一个非常大的应用程序,在MySQL数据库中存储了数千个图像和文档作为BLOBS(平均大小= 2MB),并且应用程序在具有256MB内存的服务器上运行良好。秘诀是正确的数据库结构。始终保留两个单独的表,其中一个表存储有关文件的基本信息,另一个表应该只包含blob以及用于访问它的主键。所有基本查询都将针对详细信息表运行,而另一个表仅在实际需要文件时访问,并且使用索引键访问它,因此性能非常好。

在数据库中存储文件的优点是多方面的:

  1. 需要更简单的备份系统,因为您不需要备份文件系统
  2. 控制文件安全性要容易得多,因为您可以在发布二进制文件之前进行验证(是的,您可以将文件存储在非公共目录中并读取脚本并重新调整文件,但性能不会明显加快。< / LI>
  3. (类似于#1)它清晰地分离了“用户内容”和“系统内容”,使迁移和克隆更容易。
  4. 更容易管理文件,跟踪/存储版本更改等,因为您需要更少的脚本修改来添加版本控件。
  5. 如果性能是一个大问题而安全和备份不是(或者如果你有一个好的fs备份系统),那么你可以将它存储在FS中,但即使这样我经常存储文件(如果是图像)在DB中并构建一个缓存脚本,在第一次使用它之后将其写入缓存文件夹(是的,这会占用更多的HD空间,但这几乎不是限制因素)。

    无论如何,很明显FS在很多情况下运行良好,但我个人认为数据库管理更容易,更灵活,如果写得好,性能损失也非常小。

答案 4 :(得分:10)

我们创建了一个在DB中存储图像的商店。它在开发过程中运行良好,但是一旦我们在生产服务器上测试它,页面加载时间就太高了,它给数据库服务器增加了不必要的负载。

虽然将二进制文件存储在数据库中似乎很有吸引力,但获取和操作它们会增加额外的复杂性,只需将文件保留在文件系统上并在数据库中存储路径/元数据即可避免这种复杂性。

这是永恒的辩论之一,双方都有很好的论据,但是为了我的钱,我会把图像远离数据库。

答案 5 :(得分:9)

我最近看到了这个提示列表:http://www.ajaxline.com/32-tips-to-speed-up-your-mysql-queries

提示17: 对于Web应用程序,图像和其他二进制资产通常应存储为文件。也就是说,只存储对文件的引用而不是数据库中的文件本身。

所以只需将文件路径保存到图像:)

答案 6 :(得分:6)

我在以前的项目中实现了两种解决方案(文件系统和数据库持久化映像)。在我看来,您应该将图像存储在数据库中。原因如下:

  1. 当您的应用服务器群集时,文件系统存储会更复杂。您必须拥有共享存储空间。即使您当前的环境没有群集,这也会使您在需要时更难扩展。
  2. 无论如何,您应该使用CDN作为静态内容,并将您的应用设置为原点。这意味着您的应用只会针对给定图像被点击一次,然后它将被缓存在CDN上。 CloudFront很便宜且设置简单......没有理由不使用它。为动态内容节省带宽。
  3. 开发数据库持久化图像要快得多(因而便宜)
  4. 您可以使用数据库持久图像获得参照完整性。如果要在文件系统上存储图像,则不可避免地会有没有匹配数据库记录的孤立文件,或者您将拥有包含损坏文件链接的数据库记录。这将发生......这只是时间问题。你必须写些东西来清理它们。
  5. 无论如何,我的两分钱。

答案 7 :(得分:4)

  1. 无论如何,如果没有存储文件,blob数据类型是什么?
  2. 如果您的应用程序在访问文件之前涉及授权,则更改是您a)将文件存储在DOCUMENT_ROOT之外(因此无法直接访问它们;并且可能b)发送文件的全部内容通过应用程序(当然,也许你正在做某种temporarilly-move-tohed-but-public-accessible-filename的事情)。所以无论如何都会有内存开销,你也可以从数据库中检索数据。
  3. 如果您必须将文件存储在文件系统中,请按照上面建议的Andreas进行操作,并使用您已知的内容(即相关表的主键)命名。

答案 8 :(得分:2)

我认为大多数数据库引擎已经非常先进,因此存储BLOB的数据不会产生任何缺点(膨胀的数据库等)。一个优点是,当图像已经存在于数据库中时,您没有任何断开的链接。话虽如此,我总是这样做,以便将文件存储在磁盘上并将URI提供给数据库。这取决于用途。如果页面非常动态并经常更改,则可能更容易处理img-in-db - 没有名称空间 - 问题。我不得不说它最终归结为你喜欢的东西。

答案 9 :(得分:2)

我建议您不要将图像存储在数据库中。相反,由于每个用户都将在数据库中拥有与他/她的配置文件关联的唯一ID,因此请使用该ID在服务器上物理存储图像。

e.g。如果用户的ID为23,则可以在www.yourname.com/users/profile_images/23.jpg中存储图像。然后要显示,您可以检查图像是否存在,并相应地显示它,否则显示您的通用图标。

答案 10 :(得分:2)

正如其他人所说:

  • 将图像存储在文件系统中
  • 不要费心存储文件名,只需使用用户ID(或“你已经知道”的其他任何内容)
  • 将静态数据放在不同的服务器上(即使您只使用“static.yourdomain.com”作为普通服务器的别名)

为什么?

数据库越大,获得的速度越慢。 将映像存储在数据库中会增加数据库大小。 存储文件名将增加数据库大小。

将静态数据放在不同的服务器上(别名):

  • 使扩展更容易
  • 大多数浏览器不会向同一台服务器发送两个以上的请求,方法是将静态数据放在“第二”服务器上,以加快加载速度

答案 11 :(得分:1)

经过几天的研究,我制作了一个在数据库中存储图像和二进制文件的系统。

真是太好了。我现在100%控制文件,如访问控制,图像大小调整(当然,我不动态缩放图像),统计,备份和维护。

在我的速度测试中,系统现在慢了10倍。但是,它仍未投入生产,我将实现系统缓存和其他优化。

使用MVC在SHARED主机上检查仍在开发中的这个真实示例: http://www.gt8.com.br/salaodocalcado/calcados/meia-pata/

在此示例中,如果用户已登录,则他可以看到不同的图像。所有产品图像和其他二进制文件都在DB中,而不是缓存,而不是FS。

我在专用服务器上进行了一些测试,结果远远超出预期。

因此,在我个人看来,尽管需要付出巨大努力来实现它,但是将数据存储在数据库中是值得的,并且其益处更有价值。

答案 12 :(得分:0)

正如其他人告诉你的那样,永远不要将图像存储在数据库中。 文件系统用于存储文件 - &gt;图像是文件 - &gt;将它们存储在文件系统中: - )

答案 13 :(得分:0)

刚刚测试了我的img's blob,所以。此解决方案比服务器上的图像工作速度慢。加载时间应与来自DB或http的图像相同,但不是。为什么?我敢肯定,当图像是服务器上的文件时,浏览器可以缓存它并且只加载一次,第一次。当图像从DB格式化时,每次都会再次加载。那是我的意见。也许我错误的浏览器缓存,但工作较慢(blob)。不管怎样,我的英语不好; P

答案 14 :(得分:0)

这两种解决方案的优点

在BLOBS中:

1)优点:易于管理群集,因为您不必处理服务器之间的文件同步等棘手问题

2)数据库备份也将是详尽无遗的

在档案中

1)原生缓存手工(这是以前注释的缺失点,刷新和标题,您不必在DB中重新设计(默认情况下DB不处理上次修改时间)

2)以后轻松调整大小

3)审核的简便性(只需检查文件夹是否正确)

由于所有这些原因,由于数据库的两个专业人员更容易在文件系统上复制,我强烈推荐文件!

答案 15 :(得分:0)

就我而言,我将文件存储在文件系统中。在我的images文件夹中,我根据item id(来自db的行)为每个项目创建新文件夹。并按照从0开始的顺序命名图像。所以,如果我有一个名为Items的表,那么:

       Items      
|-----|------|-----|
| ID  | Name | Date|
|-----|------|-----|
| 29  | Test1| 2014|
|-----|------|-----|
| 30  | Test2| 2015|
|-----|------|-----|
| 31  | Test3| 2016|
|-----|------|-----|

我的images目录看起来像:

images/
      29/
      30/
      31/


images/29/0.png
images/29/1.jpeg
images/29/2.gif