响应返回给客户端后清理

语境:

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

@GetMapping public DeferredResult download(/**params**/) { } 

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

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

目前,我正在使用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 } } 

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