I have a Controller which allows users to download a file.
The problem is that depending on the params sent to the controller, the controller will zip different folders and send them to the clients, and zipping can take sometimes 2 minutes, time while the user is prompted with an empty browser tab and a loading header.
Is there a way I could show a message to the user until the file is zipped and download really starts? Something like "Please wait, your file is being prepared for download!"
Thank you!
This is not specific to spring mvc - you can do this with any sort of web based action (like servlets or webwork/structs actions).
The request the user sends to perform the download should not be creating the .zip, but queue a task that creates the zip, which then another thread (threads?) can pull off and create those .zip files.
E.g,
class CreateZipController extends AbstractController {
//tokenService is soemthing that you can save a future with, and return a token for - can be anything reallly...like a map.
public ModelAndView handleRequestInternal(final HttpServletRequest request, HttpServletResponse response) throws Exception {
Future<ZipFile> zipTask = executorService.submit(new Callable<ZipFile>(){
public ZipFile call() {
return createZipFile(request);
}
});
String token = tokenService.saveTask(zipTask);
if (zipTask.isDone() {
ModelAndView mav = new ModelAndView("downloadView");
mav.addObject("url", getDownloadUrlFrom(zipTask.get().getName()));
return mav;
}
ModelAndView mav = new ModelAndView("waitView");
mav.addObject("message", "Please wait while zip is being created");
mav.addObject("token", token);
return mav;
}
}
class GetZipController extends AbstractController {
public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
String token = request.getParameter("token");
Future<ZipFile> zipTask = tokenService.getTaskFrom(token);
if (zipTask.isDone() {
ModelAndView mav = new ModelAndView("downloadView");
mav.addObject("url", getDownloadUrlFrom(zipTask.get().getName()));
return mav;
} else {
ModelAndView mav = new ModelAndView("waitView");
mav.addObject("message", "please wait while the zip is being built");
return mav;
}
}
}
Since i m not too familiar with spring mvc, the above might be slightly off (in terms of library names/conventions) but the basic idea is there - queue up the zip file creation as a task (using something like ExecutorService), and then quickly render the view. The view itself then either refreshes (use meta refresh tag), or AJAX poll another controller to see if the task is done. If it is, then redirect to the download url.