存储上传图像,SQL数据库或磁盘文件系统的最佳位置是什么?

时间:2008-12-07 23:55:40

标签: database filesystems image-uploading binaryfiles

我正在编写一个允许用户将图像上传到服务器的应用程序。我希望每天大约有20张图片都是jpeg,可能没有编辑/调整大小。 (这是另一个问题,如何在存储之前调整服务器端的图像大小。也许有人可以请求在评论中删除.NET资源等等)。 我现在想知道存储上传图像的最佳位置是什么。

  • 将图像作为文件存储在文件系统中,并在表格中创建一条记录,其中包含该图像的确切路径。

  • 或者,使用数据库服务器的“图像”或“二进制数据”数据类型将图像本身存储在表中。

我看到两者的优点和缺点。 我喜欢a)因为我可以轻松地重新定位文件,只需要更改表条目。另一方面,我不喜欢在Web服务器上存储业务数据,我真的不想将Web服务器连接到任何其他包含业务数据的数据源(出于安全原因) 我喜欢b)因为所有信息都在一个地方,并且可以通过查询轻松访问。另一方面,数据库将很快变得非常大。外包数据可能会更加困难。

19 个答案:

答案 0 :(得分:84)

我通常将文件存储在文件系统上,因为它就是它的用途,尽管有例外。对于文件,文件系统是最灵活和最高效的解决方案(通常)。

在数据库中存储文件存在一些问题 - 文件通常比平均行大得多 - 包含许多大文件的结果集将占用大量内存。此外,如果您使用使用表锁进行写入的存储引擎(例如ISAM),则您的文件表可能会被锁定,具体取决于您在那里存储的文件的大小/速率。

关于安全性 - 我通常将文件存储在文档根目录之外的目录中(不能通过http请求访问),并通过首先检查正确授权的脚本为它们提供服务。

答案 1 :(得分:37)

选项B的唯一好处是在一个系统中拥有所有数据,但这是一个错误的好处!您可能会争辩说您的代码也是一种数据形式,因此也可以存储在数据库中 - 您希望它如何?

除非你有一些独特的案例:

  • 业务逻辑属于代码。
  • 结构化数据属于数据库(关系或非关系)。
  • 批量数据属于存储(文件系统或其他)。

Files, Code, Data

没有必要使用文件系统来保存文件。相反,您可以在其上使用云存储(例如Amazon S3)或基础架构即服务(例如Uploadcare):

https://uploadcare.com/upload-api-cloud-storage-and-cdn/

但是将文件存储在数据库中是一个坏主意。

答案 2 :(得分:21)

Flickr使用文件系统 - 他们讨论原因here

答案 3 :(得分:11)

我们已经让客户在几个不同的后端上坚持选项B(数据库存储)几次,并且总是最终返回到选项A(文件系统存储)。

大型BLOB即使是SQL Server 2005也没有得到足够好的处理,这是我们尝试过的最新版本。

具体来说,我们看到了严重的膨胀,我认为可能存在锁定问题。

另一个注意事项:如果您使用的是基于NTFS的存储(Windows服务器等),您可能会考虑找到将成千上万个文件放在一个目录中的方法。我不确定为什么,但有时文件系统无法很好地应对这种情况。如果有人对此有更多了解,我很乐意听到。

但我总是尝试使用子目录来解决问题。创建日期通常适用于此:

图片/ 2008/12/17 / .JPG

...这提供了相当好的分离水平,并且在调试期间也有所帮助。当存在真正庞大的目录时,资源管理器和FTP客户端都会窒息。

编辑: 2017年的简短说明,在更新版本的SQL Server中,有许多新选项可以处理大量BLOB,这些BLOB应该避免我讨论的缺点。

答案 4 :(得分:9)

我最近创建了一个PHP / MySQL应用程序,它将PDF / Word文件存储在MySQL表中(到目前为止每个文件大到40MB)。

<强>优点:

  • 上传的文件与其他所有文件一起复制到备份服务器,不需要单独的备份策略(安心)。
  • 设置Web服务器稍微简单一点,因为我不需要上传/文件夹,并告诉我所有的应用程序它在哪里。
  • 我使用事务进行编辑以提高数据完整性 - 我不必担心孤立和丢失文件

<强>缺点:

  • mysqldump现在花了很多时间,因为其中一个表中有500MB的文件数据。
  • 与文件系统
  • 相比,总体上没有非常高的内存/ CPU效率

我称我的实现成功,它负责备份要求并简化项目的布局。对于使用该应用程序的20-30人来说,性能很好。

答案 5 :(得分:7)

我知道这是一个老帖子。但是,此页面的许多访问者都没有与此问题相关。特别是对于新手。

如何在我们的网站上传和存储图像或文件:

对于静态网站,可能没有问题,因为某些共享托管的文件存储仍然足够。当问题变得更大时,问题来自动态网站。可以处理数据库中较大的数据,但是文件(例如图像)中的较大值会成为问题。网站中有两种类型的图像:

  1. 图片来自动态博客的管理员。通常,这些图像在上传之前已经过优化。

  2. 允许用户在用户的情况下上传图像,例如头像。或者用户可以创建博客内容并从文本编辑器中放置一些图像。这种图像难以预测大小。用户可以通过调整视图大小但不调整图像大小来上传仅适用于小内容的大图像。

  3. 忽略项目编号。上面的1,快速解决项目号。如果我们的网站没有图像优化功能,可以通过以下提示临时解决2:

    1. 不允许用户通过将其重定向到图库来直接从文本编辑器上传。在此页面上,用户必须提前上传文件才能嵌入内容。此方法称为文件管理器。

    2. 使用裁剪图像功能供用户上传图像。即使用户上传非常大的文件,这也会限制图像大小。最终图像是裁剪图像的结果。我们可以在服务器端定义大小,只接受例如500Kb或更低。

    3. 现在,这只是暂时的。对于最终解决方案,重复问题:

      • 如何处理大图像存储?
      • 调整或更改扩展名。
      • 大中型网站或电子商务如何处理图像的文件存储?

      我们可以做什么:

      1. 从托管VPS的共享迁移。不够?然后通过升级到Dedicated更高。

      2. 为文件存储创建自己的服务器。谷歌搜索做到这一点。这并不像你想象的那么困难。有些人为他们的网站做这件事。

      3. 简单的方法是使用CDN文件存储服务。

      4. 好的,1和2有点贵。但我认为不是最好的解决方案。

        某些CDN服务允许您根据需要存储任意数量的Web文件。

        问题,&#34;如何从我们的网站上传文件到CDN?&#34;

        不用担心,一旦您注册,通常是免费的,您将获得如何上传文件并从/到您的网站获取链接的指导。您将获得API等等。这很容易。

        有些提供商为我们提供14天免费服务,但存储和带宽有限。但这对于起点来说还可以。唯一的问题是因为人们从不尝试过。

        希望它能为新手提供帮助。

答案 6 :(得分:6)

我在我的网站上使用上传的图片,我肯定会说选项a)。

我强烈建议的另一件事是立即将文件名从用户命名的照片更改为更易于管理的内容。例如,具有唯一标识每张图片的日期和时间的东西。

它还有助于删除用​​户的任何奇怪字符的文件名,以避免将来出现并发症。

答案 7 :(得分:6)

绝对调整图像大小,如果可以的话,检查它的格式。有些恶意文件被不知情的主机上传和提供服务 - 例如,GIFAR漏洞允许您在GIF文件中隐藏恶意Java小程序,然后可以在当前上下文中读取cookie并将它们发送到另一个站点以进行跨站点脚本攻击。调整图像大小通常可以防止这种情况,因为它会对嵌入的代码进行调整。虽然这种攻击已经被JVM补丁修复,但是天真地提供二进制文件而不擦除它们会让你面临各种各样的漏洞。

请记住,大多数病毒扫描程序只能针对文件系统运行 - 如果将二进制文件存储在数据库中,则无法轻松地对其进行扫描。

答案 8 :(得分:3)

对于自动调整大小,请尝试使用imagemagick ...它用于许多主要的开源内容/照片管理系统......我相信它有一些.net扩展名。

答案 9 :(得分:3)

在SQL Server 2008中有一种称为filestream datatype的混合方法在RunAs Radio #74上被讨论过,这有点像两全其美。大多数人没有2008年的表现,但如果你这样做,这个选项看起来很酷

答案 10 :(得分:3)

大多数实现都是选项A.

使用选项B,当您将数据库中的这些位编组为可以在浏览器上显示的内容时,您可以打开一大堆whoop4ss ...此外,如果数据库已关闭,则图像不可用。< / p>

我认为空间不是太大的问题...... Terabyte驱动器现在只需几百美元。

我们正在实施选项A,因为我们没有时间或资源来执行选项B.

答案 11 :(得分:3)

这基本上就是我做的。

  1. 将上传的图像存储在临时目录或内存中。
  2. 在永久存储之前处理该图像。 2.1。色彩校正 2.2。压缩 2.3。根据图像尺寸创建多个副本 2.4。使用.xl,.lg,.md,.sm等后缀重命名
  3. 将所有已处理的图像文件(来自单个文件)打包到文件夹名称为id的文件夹中,该文件夹将与image file name一起存储在任何行/文档的数据库中(或者可以是随机名称)如图像名称)。
  4. 如果不存在,请创建 yyyy / mm / d path文件夹。例如2016/08/21。请记住路径和存储在数据库中的相同文档和行。
  5. 将图片id文件夹移至path文件夹。 (Path文件夹可能位于/ var / web-content文件夹中。)
  6. 刷新内存缓冲区或删除临时文件。
  7. 当您需要访问文档中提到的任何图像时,您拥有文件夹的路径和ID,而不是包含图像。例如/var/web-content/{{path}}/{{id}}/image-file-name.sm.jpg

    这样,如果您必须删除所有已处理的图像文件,只需递归删除该文件夹及其内容。

答案 12 :(得分:2)

绝对,积极的选择A.其他人已经提到数据库通常不能很好地处理BLOB,无论它们是否设计成这样做。另一方面,文件系统为这些东西而活。您可以选择使用RAID条带化,在多个驱动器之间传播图像,甚至可以将它们分布在地理位置不同的服务器上。

另一个优点是您的数据库备份/复制将是可怕的。

答案 13 :(得分:2)

选项A.

加载图像后,您可以在保存之前验证格式并调整其大小。有许多.Net代码示例用于调整http://www.codeproject.com上的图像大小。例如:http://www.codeproject.com/KB/cs/Photo_Resize.aspx

答案 14 :(得分:2)

出于安全原因,最佳做法是避免IE's Content Sniffing导致的问题,这些问题可能允许攻击者在图像文件中上传JavaScript,这可能会在您网站的上下文中执行。所以你可能想要在存储它们之前以某种方式转换图像(裁剪/调整它们)以防止这种攻击。 This answer还有其他一些想法。

答案 15 :(得分:2)

好吧,我有一个类似的项目,用户将文件上传到服务器上。在我看来,选项a)是最好的解决方案,因为它更灵活。您必须做的是将图像存储在由子目录分类的受保护文件夹中。主目录必须由管理员设置,因为内容必须不运行脚本(非常重要)和(读,写)保护​​,以便在http请求中不可访问。

我希望这会对你有所帮助。

答案 16 :(得分:2)

我们使用A.我会将它放在共享驱动器上(除非您不打算运行多个服务器)。

如果时间不适合您,那么您可以调查缓存机制。

答案 17 :(得分:1)

如果它们是不需要编辑的小文件,那么选项B不是一个糟糕的选择。我更喜欢这样写逻辑来存储文件并处理疯狂的目录结构问题。在一个目录中很多文件很糟糕。 EMKAY?

如果文件很大或需要不断编辑,特别是办公室等程序,那么选项A是最好的选择。

对于大多数情况,这是一个偏好的问题,但是如果你选择A,那么只需在目录中没有太多文件。如果选择选项B,则将包含BLOBed数据的表放在其自己的数据库和/或文件组中。这有助于维护,尤其是备份/恢复。您的常规数据可能相当小,而您的图像数据随着时间的推移会巨大

答案 18 :(得分:1)

这取决于您的要求,特别是数量,用户和搜索频率。但是,对于中小型办公室,最好的选择是使用Apple Photos或Adobe Lighroom等应用程序。它们专门用于存储,编目,索引和组织此类资源。但是,对于具有强大存储需求和大量用户的大型组织,建议使用数字资产管理实例化内容管理平台,如Nuxeo或Alfresco;两者都提供了非常好的资源,可以使用简化的方法管理大量数据来检索它们。并且,非常重要:两个平台都有一个免费(开源)选项。