Асинхронная загрузка файлов в Spring

Вот что я делаю. Я хочу загрузить составной файл через 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-контракт, желая выполнить внутреннюю асинхронную обработку файлов.

9
задан skaffman 18 May 2012 в 12:47
поделиться