Вот что я делаю. Я хочу загрузить составной файл через Ajax в свое веб-приложение Spring. Когда сервер получает POST-запрос, он создает номер тикета в базе данных. Затем он запускает поток, который обрабатывает фактическую загрузку файла. Затем сервер возвращает номер билета.
Я использую CommonsMultipartResolver для обработки запроса и установил для флага resolveLazily значение true, чтобы Multipart не разрешался сразу.
Вот что-то похожее на то, что у меня есть.
@Controller
public class myController{
@RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
@ResponseBody
public String upload(MultipartHttpServletRequest request, String fileName){
String ticket = dao.createUploadTicket(fileName);
Runnable run = new Runnable(){
@Override
public void run(){
dao.writeUpdate(ticket, "Getting data from request");
final MultipartFile file = request.getFile("theFile");
dao.writeUpdate(ticket, "Multipart file processed");
try {
dao.writeUpdate(ticket, "Saving file to disk");
file.transferTo(new File("/myDirectory"));
dao.writeUpdate(ticket, "File saved to disk");
}
catch(Exception e){
dao.writeUpdate(ticket, "File upload failed with the exception " + e.toString());
}
}
};
Thread t = new Thread(run);
t.start();
return ticket;
}
}
Суть в том, что номер тикета можно использовать для получения обновлений прогресса. Допустим, загружается большой файл. Клиент, выполнивший загрузку файла POST (скажем, в данном случае Ajax-запрос), может сделать это асинхронно и вернуть номер тикета. Клиент может использовать этот номер тикета, чтобы определить этап загрузки файла и отобразить информацию на другой странице.
Другое использование заключается в том, что у меня может быть HTML-страница, которая делает запрос на сервер для всех номеров билетов, а затем показывает «живое» представление всех загрузок файлов, которые происходят на сервере.
Мне не удалось заставить это работать, потому что как только контроллер возвращается, Spring вызывает cleanupMultipart() в CommonsMultipartResolver.Поскольку для флага resolveLazily установлено значение false, при вызове cleanupMultipart() он начнет разрешать и инициализировать составные файлы. Это приводит к состоянию гонки между вызовом «request.getFile(«theFile»);» в runnable и вызов cleanupMultipart() в конечном итоге приводит к исключению.
У кого-нибудь есть идеи? Я нарушаю здесь какой-то HTTP-контракт, желая выполнить внутреннюю асинхронную обработку файлов.