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(使用前将#替换为@)