PHP存储图像在MySQL或不?
我已经用PHP构build了一个小型Web应用程序,用户必须先login。login后,我打算在其“configuration文件”中显示一个小缩略图。
我将不得不确保图像低于特定的尺寸以节省空间,或者确保它是特定的分辨率,或者两者兼而有之,或者甚至可以使用诸如图像魔术师之类的东西来缩小图像。
不知道最好的方法是什么,欢迎任何想法。
此外,我一直在努力研究如果最好将图像存储在MySQL的users
表中作为一个blob,或者可能是一个独立的images
表与一个唯一的ID,只是在users
表中存储适当的图像ID,或者直接将上传的文件保存在服务器上(也可以通过上传页面)并将文件另存为theUsersUniqueUsername.jpg
。 最好的select?
我find了一个保存图像到MySQL的教程: http : //www.phpriot.com/articles/images-in-mysql
我只是一个业余爱好程序员,从来没有做过这样的事情,所以很多例子,和/或很多细节非常感谢。
总是依赖于上下文,但是通常,我将文件系统上的用户映像存储在名为/content/user/{user_id}.jpg
的文件夹中,尽可能less地打扰数据库。
我会build议将图像存储为文件,然后在数据库中具有文件URI。 如果将所有图像存储在数据库中,稍后您可能会遇到一些缩放问题。
看看这个答案也是:
微软对SQL Server的build议曾经是,为了速度和大小,将图像存储在文件系统中,并在数据库中存储链接。 我认为他们已经软化了他们的偏好,但我仍然认为这是一个更好的主意,因为它将在数据库中不占用空间。
使用BLOB的开销要比大多数人想要的less得多,特别是如果你设置正确的话。 如果您使用单独的服务器运行数据库来存储二进制文件,那么您实际上可以根本不使用文件系统,并避免文件系统的任何开销
这就是最简单/最好的方法,除非你自己有几台服务器将它们存储在文件系统中
-
不要将文件的绝对URL存储在数据库中,只存储唯一部分(可能还有一两个文件夹),例如
2009/uniqueImageName.jpg
或uniqueImageName.jpg
。 然后,在你的页面中,只需要将主机和其他文件夹添加到前面,这样,在移动图像时就可以灵活地进行操作 – 只需在PHP / ASP.NET页面中更改一行或两行即可。 -
没有必要为了安全性而在文件根目录之外存储 – 具有DENY FROM ALL的
.htaccess
文件将工作相同并且提供更大的灵活性 -
为了安全起见,不需要“分stream”图像,只需要有一个
getImage.php
页面或者其他的东西,然后不要在image
的src
中插入实际的URL,而是使用像getImage.php?file=uniqueImageName.jpg
这样的东西。 然后,getImage.php
文件可以检查用户是否被授权,并获取图像(或不)。 -
使用一个保存为唯一的名字(最好是一个整数,即主键),在存储时,某些文件系统(如Windows)不区分大小写,所以
JoeBloggs.jpg
和joebloggs.jpg
对于数据库是唯一的,文件系统,所以会覆盖另一个。 -
为图像使用单独的表格,并将图像的主键存储在用户表格中。 如果你想在未来添加更多的领域或做出更改,将会更容易 – 这也是一个很好的做法。
如果你担心search引擎优化和类似的东西,在上传时将图像的原始文件名存储在另一个字段中,然后可以在输出中使用它(例如在alt
标签中)。
挑战传统的智慧!
当然这是依赖于上下文的,但是我有一个非常大的应用程序,在MySQL数据库(平均大小= 2MB)中有成千上万的图像和文档存储为BLOBS,应用程序在256MB内存的服务器上正常运行。 秘密是正确的数据库结构。 始终保留两个单独的表,其中一个存储有关文件的基本信息,另一个表应该只包含blob加上访问它的主键。 所有的基本查询都将针对细节表运行,而另一个表只在文件实际需要时才能访问,并且使用索引键访问,所以性能非常好。
将文件存储在数据库中的优点是多重的:
- 需要更简单的备份系统,因为您不需要备份文件系统
- 控制文件的安全性要容易得多,因为在释放二进制文件之前可以进行validation(是的,您可以将该文件存储在非公共目录中,并且可以读取并回滚文件,但性能不会显着提高。
- (与#1类似)它清晰地分离出“用户内容”和“系统内容”,使迁移和克隆变得更加简单。
- 更轻松地pipe理文件,跟踪/存储版本更改等,因为您需要更less的脚本修改来添加版本控制。
如果性能是一个大问题,安全和备份不是(或者如果你有一个好的FS备份系统),那么你可以将它存储在FS中,但即使如此,我经常在数据库中存储文件(在图像的情况下)并build立一个caching脚本,在第一次使用后将图像写入caching文件夹(是的,这使用了更多的HD空间,但这几乎不是限制因素)。
无论如何,很显然FS在许多情况下运行良好,但我个人发现DBpipe理更容易和更灵活,如果写得好,性能处罚非常小。
我们创build了一个在DB中存储图像的商店。 它在开发过程中运行良好,但是一旦我们在生产服务器上testing,页面加载时间过高,并且给DB服务器增加了不必要的负载。
虽然将二进制文件存储在数据库中似乎很有吸引力,但是获取和操作它们会增加额外的复杂性,只需将文件保存在文件系统中并将path/元数据存储在数据库中即可避免。
这是那些永恒的辩论之一,双方都有出色的论点,但是为了我的钱,我会把图片从数据库中删除。
我最近看到这个提示的列表: http : //www.ajaxline.com/32-tips-to-speed-up-your-mysql-queries
提示17:对于您的Web应用程序,图像和其他二进制资源通常应该作为文件存储。 也就是说,只存储对文件的引用,而不是数据库中的文件本身。
所以只需将文件path保存到图像:)
在以前的项目中,我实现了两个解决scheme(文件系统和数据库持久化图像)。 在我看来,你应该将图像存储在数据库中。 原因如下:
- 当您的应用程序服务器进行群集时,文件系统存储更为复杂。 你必须有共享存储。 即使您的当前环境未被聚类,也会使您在需要时更难扩展。
- 无论如何,您应该为静态内容使用CDN,并将您的应用设置为原始位置。 这意味着你的应用程序只会被命中一次给定的图像,然后它将被caching在CDN上。 CloudFront很便宜,设置简单…没有理由不使用它。 为您的dynamic内容保存带宽。
- 开发数据库持久化图像要快得多(因而也便宜)
- 您可以通过数据库持久图像获得参照完整性。 如果要在文件系统上存储图像,则不可避免地会出现没有匹配数据库logging的孤立文件,或者您将拥有包含损坏文件链接的数据库logging。 这将发生…这只是一个时间问题。 你必须写些东西来清理这些。
不pipe怎样,我的两分钱。
- 无论如何,如果不是用于存储文件,blob数据types是什么?
- 如果您的应用程序在访问文件之前涉及授权,则更改的方法是:a)将文件存储在DOCUMENT_ROOT之外(因此无法直接访问它们;可能b)通过应用程序发送文件的全部内容(当然,也许你正在做一些临时移动到哈希,但公开可访问的文件名的东西)。 所以无论如何内存开销,你也可能从数据库中检索数据。
- 如果您必须将文件存储在文件系统中,请按照Andreas上面的build议进行操作,并使用您已知的东西(即相关表的主键)对其进行命名。
我认为大多数数据库引擎已经很先进了,存储数据的BLOB不会产生任何缺点(臃肿的数据库等)。 一个好处是,当图像已经在数据库中时,没有任何断开的链接。 也就是说,我自己总是这样做,以便将文件存储在磁盘上并将URI提供给数据库。 这取决于使用情况。 如果页面非常dynamic并经常更改,则可能更容易处理img-in-db – 没有命名空间问题。 我不得不说,它结束了你喜欢的。
我build议你不要在你的数据库中存储图像。 相反,因为每个用户都将有一个唯一的ID与他/她在数据库中的configuration文件相关联,使用该ID在服务器上物理存储图像。
例如,如果用户的ID为23,则可以在www.yourname.com/users/profile_images/23.jpg中存储图像。 然后显示,您可以检查图像是否存在,并相应地显示,否则显示您的通用图标。
正如其他人所build议的:
- 将图像存储在文件系统中
- 不要费心去存储文件名,只需使用用户名(或者“你已经知道的”)
- 把静态数据放在不同的服务器上(即使你只是使用“static.yourdomain.com”作为你的普通服务器的别名)
为什么?
数据库越大,得到的速度越慢。 将图像存储在数据库中会增加数据库的大小。 存储文件名将增加您的数据库大小。
将静态数据放在不同的服务器(别名)上:
- 使扩展更容易
- 大多数浏览器不会向同一台服务器发送两个以上的请求,通过将静态数据放在“第二”服务器上加速加载
经过几天的研究,我做了一个系统存储图像和二进制数据库。
这太棒了。 我现在对文件有100%的控制权,比如访问控制,图像大小调整(当然我不会dynamic地调整图像),统计数据,备份和维护。
在我的速度testing中,系统现在慢了10倍。 但是,它还没有在生产中,我将实现系统caching和其他优化。
使用MVC,在SHARED主机上检查这个真正的例子,仍在开发中: http : //www.gt8.com.br/salaodocalcado/calcados/meia-pata/
在这个例子中,如果用户login,他可以看到不同的图像。 所有的产品图像和其他二进制文件都在DB中,没有被caching,不在FS中。
我在专用服务器上做了一些testing,结果远远超出了预期。
所以,我个人认为,虽然需要很大的努力来实现,但是在DB中存储图像是值得的,而且好处也是值得的。
正如其他人告诉你的,不要将图像存储在数据库中。 文件系统用于存储文件 – >图像是文件 – >将它们存储在文件系统中:-)
只是testing我的IMG的一团糟,所以。 此解决scheme比文件服务器上的映像慢。 加载时间应该与来自DB或http的图像相同,但不是。 为什么? 我确定,当图像是在服务器上的文件,浏览器可以caching它,并只加载一次,第一次。 当图像形成DB时,每次都要重新加载。 这是我的想法。 也许我错了浏览器caching,但工作较慢(blob)。 不pipe我的英语是什么; P
这是两种解决scheme的优点
在BLOBS:
1)优点:pipe理集群的容易性,因为您不必处理棘手的问题,如服务器之间的文件同步
2)数据库备份也将是详尽的
在文件中
1)本地caching(这是以前的意见,这是刷新和标题,你将不必重新devise数据库(数据库没有处理上次修改时间默认情况下)的缺失点)
2)稍后容易resize
3)轻松适度(只需通过您的文件夹来检查是否一切正确)
由于所有这些原因,既然数据库的两个专业人员更容易在文件系统上复制我强烈build议文件!
在我的情况下,我将文件存储在文件系统中 。 在我的图像文件夹中,我创build了基于项目ID(从数据库行)命名的每个项目的新文件夹。 并命名图像从0开始的顺序。所以,如果我有一个名为这样的项目表:
Items |-----|------|-----| | ID | Name | Date| |-----|------|-----| | 29 | Test1| 2014| |-----|------|-----| | 30 | Test2| 2015| |-----|------|-----| | 31 | Test3| 2016| |-----|------|-----|
我的图像目录看起来像这样:
images/ 29/ 30/ 31/ images/29/0.png images/29/1.jpeg images/29/2.gif
等等