gpt4 book ai didi

database - 将上传的文件存储在Web应用程序的文件系统中时如何处理问题?

转载 作者:行者123 更新时间:2023-12-02 09:47:22 25 4
gpt4 key购买 nike

我正在构建一个Web应用程序,用户可以在其中创建报告,然后为创建的报告上载一些图像。当用户单击报告页面上的按钮时,这些图像将在浏览器中呈现。这些图像是机密的,只有授权用户才能访问它们。

我知道在数据库,文件系统或亚马逊S3之类的服务中存储图像的利弊。对于我的应用程序,我倾向于将图像保留在文件系统中,并将图像的路径保留在数据库中。这意味着我必须处理与分布式事务管理有关的问题。我需要一些有关如何处理这些问题的建议。

1-我相信正确的解决方案之一是使用JTA和XADisk等技术。我对这些技术不是很了解,但是我相信两阶段提交是实现自动化的方式。我正在使用MySQL作为数据库,并且MySQL似乎支持两阶段提交。这种方法的问题在于XADisk似乎不是一个活跃的项目,并且关于它的文档并不多,而且我对这种方法的来龙去脉并不了解。我不确定是否应该投资这种方法。

2-我相信我可以避免因我的应用程序违反ACID属性而引起的一些问题。上传图像时,我可以先将文件写入磁盘,如果此操作成功,则可以更新数据库中的路径。如果数据库事务失败,则可以从磁盘上删除文件。我知道那仍然不是防弹。 db事务之后可能会出现电力短缺,或者磁盘可能暂时没有响应等。我知道也存在并发问题,例如,如果一个用户尝试修改上载的图像而另一个用户尝试在以下位置删除它:同时会出现一些问题。仍然可以在我的应用程序中进行并发更新的机会相对较低。

我相信,如果发生这种特殊情况,我可以使用磁盘上的孤立文件或数据库上的孤立镜像路径。如果文件路径存在于db中,而不存在于文件系统中,那么我可以在报告页面上向用户显示通知,他可能会尝试重新上传图像。文件系统中的孤立文件不会有太大问题,我可能会不时运行一个过程来检测此类文件。不过,我对这种方法不太满意。

3-最后一个选项可能是根本不将文件路径存储在db中。我可以构建文件系统,以便可以推断代码中的文件路径并立即加载所有图像。例如,我可以为每个报告创建一个文件夹,其名称为报告ID。提出加载报告图像的请求后,由于知道报告ID,因此可以立即加载图像。最终可能会导致文件系统中有大量文件夹,而且我不确定这种设计是否可以接受。并发问题在此方案中仍将存在。

对于我应该采用哪种方法,我将不胜感激。

最佳答案

我相信您正在尝试变得非常正确,也许并不需要那么多,但是前段时间我也遇到了类似的情况,并探索了不同的可能性。我不喜欢与您的选项1一致的选项,但是关于选项2和3,我有不同的成功方法。

让我们首先总结一下关注的 list :

  • 您想要保存文件
  • 您希望文件路径链接到相应的实体(即报告)
  • 您不希望文件路径链接到不存在的文件
  • 您不希望文件系统中的文件未链接到任何报告

  • 以及不同的方法:

    1.使用数据库

    您可以使用任何关系数据库来确保数据库中几乎所有事务,并且使用 S3可以确保新对象和新对象上载后的写后读取一致性。如果对对象进行 PUT并得到 200 OK,则该对象将可读。现在,如何将所有这些放在一起?您需要跟踪该过程。我可以想出两种方式:

    1.1带有进度表
  • 上载请求将保存到一个表,其中包含识别此文件,报告ID,临时上载的文件路径,目标路径和状态列
  • 所需的所有内容
  • 您保存文件
  • 如果文件安全失败,则可以更新表中的记录或将其删除
  • 如果成功保存文件,请使用transaction:
  • 以成功状态
  • 更新进度表
  • 更新您实际保存关系报告表的表
  • 具有cron,但不检查文件系统,而是检查进程表。如果文件系统中有任何孤立的文件,则肯定已将其添加到表中(它是第1点)。在这里,您可以决定是否要删除文件,或者如果您有足够的信息,则可以继续中止过程触发点4。

  • 相同的报告图像关系表,带有一些额外的状态列。

    1.2使用队列系统

    像RabbitMQ,SQS,AMQ等

    可以使用任何队列系统而不是db表来执行非常类似的方法。我不会提供太多细节,因为它更多地取决于您的实际基础结构,而仅仅是总体思路。
  • 上传请求进入队列,您发送一条消息,其中包含识别此文件,报告ID以及可能需要的最终路径的所有信息。
  • 您上传文件
  • 辅助程序读取队列中的待处理消息并进行工作。仅当一切顺利时,该消息才被标记为已使用。
  • 如果失败,则消息自然会返回到队列
  • 在下一次阅读消息时,工作人员可以有足够的信息来查看是否有要恢复的工作,如果无法继续,甚至可以删除文件

  • 在这两种情况下,并发问题都无法直接解决,但可以解决(在第一情况下依靠数据库锁,在第二种情况下依靠FIFO队列),但总是需要一些应用程序逻辑

    2.无DB

    在某种程度上,如果我们可以将其辩护为适当的 convention over configuration设计,那么没有数据库的系统将是完全可以接受的。
    您必须处理三件事:
  • 保存文件
  • 读取文件
  • 确保文件系统的结构是可管理的

  • 让我们从3开始:

    资料夹结构
  • 通常,像report id的一个文件夹之类的东西太简单了,可能很难维护,最终也太简单了。这会引起问题,因为如果我们有一个images文件夹,每个报告一个文件夹,而明天您少说200k个报告,那么images文件夹将有200k元素,甚至ls也会花费太多时间,对于任何编程语言而言尝试访问。那会杀死你的
  • 您可以考虑更复杂的事情。就个人而言,就像我10年前从Magento 1中学到的一种方法,从那以后我使用了很多东西:使用遵循第一个外部规则的文件夹结构,但是扩展了带有文件名本身的规则。
  • 我们要保存产品图像。图像名称为:myproduct.jpg
  • 第一个规则是:对于产品图片,我使用/media/catalog/product
  • 然后,为了避免在同一张图片中出现许多图片,我在图片名称的每个字母(最多一定数量的字母)中创建一个文件夹。假设3。所以我的最终文件夹将类似于/media/catalog/product/m/y/p/myproduct.jpg
  • 这样,很清楚在哪里保存任何新图像。您可以使用报告ID,类别或对您有意义的任何操作来执行类似的操作。最终目标是避免过于平坦的结构,并创建一棵对您有意义的树,并且可以轻松地对其进行自动化。

  • 然后将我们带到下一部分:

    读和写。

    我在成功之前实施了类似的系统。它使我可以轻松保存文件,并且可以在纯动态位置轻松地检索它们。这里的部分是:
  • S3(但是您可以使用任何文件系统)
  • 一个小型微服务,充当读取和写入的代理。
  • 一些 namespace 系统和附加的逻辑。

  • 逻辑很简单。命名空间让我知道文件将保存在哪里。例如, namespace 可以是 companyname/reports/images

    假设开发一个用于读取和写入的微服务:

    为了保存文件,它会收到:
  • namespace
  • 实体ID(即您要报告)
  • 文件上传

  • 它会做:
  • 基于我对该命名空间的规则,并且id和文件名会将文件保存在此文件夹
  • 它不返回物理位置。客户仍然不知道。

  • 然后,为了进行阅读,客户端将使用也使用约定的URL。例如,您可以拥有类似
    https://myservice.com/{NAMESPACE}/{entity_id}
    并且基于逻辑,微服务将知道在存储中的哪里找到并返回图像。

    如果每个报告中有一张以上的图片,则可以执行不同的操作,例如:
    -您可能想在路径中添加第三个子弹,例如 https://myservice.com/{NAMESPACE}/{entity_id}/1 https://myservice.com/{NAMESPACE}/{entity_id}/2等...
    -如果是供内部应用程序使用,则可以有一个端点返回所有合格图像的列表,可以说 https://myservice.com/{NAMESPACE}/{entity_id}返回包含所有图像URL的数组

    我的实现方法是使用非常简单的yml config定义逻辑,并使用非常简单的代码读取该配置。那让我有很大的灵活性。例如,如果报告属于不同的公司或属于不同的报告类型,则将报告保存在总共不同的路径或服务器或s3存储桶中

    关于database - 将上传的文件存储在Web应用程序的文件系统中时如何处理问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61797379/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com