java - 响应返回给客户端后清理

标签 java spring spring-boot

上下文:

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

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

}

由于文件数量和文件大小,不可能将所有文件都保存在内存中(即我必须从外部服务读取文件 block ,将它们存储到临时目录,创建 zip 存档,写入文件以 zip block 的形式,在归档完成后删除所有临时文件 - 此时我只剩下磁盘上的归档文件 - 然后将 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));
        }
    }
}

我考虑过的另一种方法:

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

在您看来,哪种方式是处理这种情况的最佳方式?

最佳答案

正如 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
    }
}

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

关于java - 响应返回给客户端后清理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52387380/

相关文章:

java - 使用 jsoup java 从文本中检索 HTML 结构

java - XSLT 从两个不同的源读取(XML 文件和 Excel 工作表)

javascript - Angular 无法读取未定义的属性 'navigate'

java - JScrollBar 中的 Page Up/Down 事件

java - 通过java程序改变网络设置

java - 列出 Spring Security 中的用户

reactjs - 为什么迁移到 https 会中断客户端和服务器之间的通信?

java - Spring 5.1 + Tomcat 9 + Java 10 + 模块化项目 = java.lang.NoClassDefFoundError : org/springframework/core/io/Resource

java - Spring Neo4J REST 错误 - nodeStateTransmitter

java - Spring Reactor Mono 在返回数据之前等待订阅者完成其任务