响应返回给客户端后进行清理

2024-01-06

Context:

我有一个用于下载 zip 存档的端点。

@GetMapping
public DeferredResult<StreamingResponseBody> download(/**params**/) {

}

由于文件数量和文件大小的原因,将所有文件保存在内存中是不可能的(即我必须从外部服务读取文件块,将它们存储到临时目录,创建 zip 存档,将文件分块写入到zip,归档完成后删除所有临时文件 -此时我只剩下磁盘上的存档- 然后将 zip 流式传输回客户端)。

我已经设法实现了该功能,但我不确定哪种是在请求后进行清理的最佳方法(请注意,该服务由多个客户端使用 - 因此多个下载应该能够同时发生)。

目前,我正在使用HandlerInterceptor为存档中的文件生成一个随机名称preHandle方法并将其作为请求属性传递。请求属性将传递到生成存档的服务并用作存档名称。然后,在afterCompletion拦截器的方法中,我从请求属性中读取存档名称并删除存档。

class ZipInterceptor implements HandlerInterceptor {

    public static final String ZIP_ATTRIBUTE_NAME = "zipName";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if(isApplicable(request)){
            request.setAttribute(ZIP_ATTRIBUTE_NAME, generateZipName());
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        if(isApplicable(request)){
            deleteZip((String)request.getAttribute(ZIP_ATTRIBUTE_NAME));
        }
    }
}

我考虑过的另一种方法:

  • 将存档名称返回给客户端(作为标头或作为下载文件的名称)并依靠客户端调用新端点来删除存档。主要缺点是我无法强制客户端使用此协议(并且可能最终导致磁盘已满)。
  • 每小时(或其他时间间隔)运行一次作业并清理旧档案。缺点是我不确定文件是否完成流回客户端(因此对于足够大的文件,任何时间间隔都会删除尚未完成流的文件)。

您认为哪种方法是处理这种情况的最佳方法?


正如 JB Nizet 在评论中指出的那样,最好的方法是根本不将文件存储在磁盘上.

如果您的特定上下文在请求返回到客户端后在磁盘上留下了文件,您可以使用下一种方法来删除它们。

class CleanupInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // do cleanup here
    }
}

如果有人找到更优雅的解决方案来解决这个问题,请在此处发布您的答案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

响应返回给客户端后进行清理 的相关文章

随机推荐

  • 如何从正则表达式创建随机字符串

    我想从正则表达式生成一个随机字符串 example random string 0 9 4 gt 7895 random string 0 9 4 gt 0804 random string 0 9 A Z 4 gt 9ZE5 random
  • 如何在lucene中使用tf idf相似度对文档进行排名

    在创建索引和搜索查询的基本代码中 我想使用 TFIDFsimilarity 对检索到的文档进行排名 但我收到错误 无法实例化类型 TFIDFSimilarity 我的代码如下 public class TFIDF T private sta
  • 在 WooCommerce 中对特定类别的最便宜商品进行折扣

    我喜欢根据产品类别打折 Woocommerce 中最便宜的购物车商品 基于 Woocommerce 中成本较低的产品的购物车折扣 https stackoverflow com questions 49693564 cart discoun
  • org.w3c.dom.DOMException:HIERARCHY_REQUEST_ERR

    我对此已经关注太久了 无法弄清楚我做错了什么 因此 我正在尝试为某些内容生成 Xades 签名 不幸的是我总是遇到同样的错误 HIERARCHY REQUEST ERR 这是我的 XML 文档
  • 聚合时间戳数据的更好方法?

    我正在处理非统一收集的时间戳索引数据 最终将按每分钟 每小时计算统计数据 我想知道按时间段聚合的最佳方法是什么 我目前计算两个 lambda 函数 然后将两列添加到数据框中 如下所示 h lambda i pd to datetime i
  • 为什么我的桌面视图很慢?

    我正在制作一个加载了一些 NSArray 的表格视图 该单元格包含两个标签和一个加载了 URL 图像的背景图像视图 问题是 tableview 的滚动很慢 就像冻结或其他什么 我认为这是因为 Imageview 但我能做什么 这是我的一些代
  • 如何使用 Maven 程序集插件 jar-with-dependencies 在 JAR 中包含自定义文件

    我需要在最终的 JAR 中包含自定义文件 com app log4 properties 使用 jar with dependencies 时如何将一个文件添加到我的 JAR 中 现在该 JAR 中只有类文件 我在用着 mvn assemb
  • 如何对对象进行版本控制?

    为了解释这一点 请查看下面正在更改的对象 obj a 1 b 2 Version 1 obj a 2 Version 2 obj c 3 Version 3 我希望能够获得该对象的任何这些版本 例如得到obj从版本 2 开始 我不想每次更新
  • Rails 3.1:如何仅为 Web 应用程序运行初始化程序(rails 服务器/unicorn/等)

    我的网络应用程序需要加密其会话数据 我设置的是 config initializers encryptor rb require openssl require myapp encryptor MyApp Encryptor config
  • 中断运行nashorn脚本的java线程

    在下面的代码中 我让 JavaScript 在与主线程不同的单独线程中运行 该脚本是一个无限循环 因此需要以某种方式终止它 如何 脚本开始运行后 调用 cancel 不起作用 但如果我在线程初始化后调用 cancel 它将终止它 注释掉的行
  • Capistrano 和从 Github 部署网站

    因此 我有一个我认为相当简单的 Capistrano 用例 我想从 Github 部署一个 PHP 站点 但我遇到了很多问题 当我跑步时cap deploy Capistrano 能够克隆 Github 存储库 deploy update
  • 卡夫卡消费者偏移最大值?

    我正在谷歌搜索并阅读 Kafka 文档 但我无法找到消费者偏移量的最大值以及最大值之后是否存在偏移量环绕 我知道 offset 是一个 Int64 值 所以最大值是 0xFFFFFFFFFFFFFFFF 如果存在wraparound Kaf
  • 我可以使用 Eclipse 将 JavaDoc 轻松添加到包中吗?

    我使用 javadoc 来记录我的类和方法 我也想在我的包中添加一些概述信息 我喜欢 Eclipse 在我输入后为每个类或方法创建匹配文档注释的存根
  • 获取ttk.Frame的默认背景

    我通过调整这个将滚动条与 ttk 笔记本结合起来example https stackoverflow com questions 3085696 adding a scrollbar to a grid of widgets in tki
  • App.config dllmap条目可移植性

    dllmap 配置文件条目在 Mono 中用于将对 Windows DLL 的请求映射到 Linux so 库 但似乎如果 Microsoft 的 NET 框架尝试解析具有此类条目的配置文件 则会发生错误 因为它不理解 dllmap 我认为
  • “data.Length==0”或“data==string.Empty”哪个更有效?

    我想检查是否有变量字符串data包含空字符串 哪个效率更高 data Length 0 or data string Empty 我忘了说 data已经检查过 保证不是null 1亿次迭代的测试结果 Equality operator 79
  • 用于从 H/W 寄存器读取的位字段

    我想从32位寄存器中读取第2位 第5位和第6位 我决定使用结构位字段来存储它们 下面的数据结构正确吗 struct readData int unwanted 1 int reqbit1 1 int unwanted1 2 int reqb
  • Worksheet.Protect AllowDeletingRows 不允许删除行

    在我的工作簿中 我使用以下代码保护 Workbook Open 上的所有工作表 ws Protect Password password UserInterFaceOnly True AllowFormattingColumns True
  • Android Lunar Lander 线程处理替代方案

    和许多 Android 编程新手一样 我使用 Lunar Lander 作为实现 SurfaceView 的指南 我正在通过创建 PONG 版本来练习 代码的基本结构与LunarLander相同 显然 我很快就发现了月球着陆器中的错误 我解
  • 响应返回给客户端后进行清理

    Context 我有一个用于下载 zip 存档的端点 GetMapping public DeferredResult