Spring中的异步文件上传

时间:2012-05-18 23:27:41

标签: java spring-mvc file-upload asynchronous apache-commons-fileupload

这就是我正在做的事情。我想通过Ajax将multipart文件上传到我的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就会在CommonsMultipartResolver中调用cleanupMultipart()。由于resolveLazily标志设置为false,因此当调用cleanupMultipart()时,它将开始解析并初始化multipart文件。这导致调用“request.getFile(”theFile“)之间的竞争条件;”在runnable和cleanupMultipart()调用中最终导致异常。

有人有什么想法吗?我想通过做后端异步文件处理来打破某种HTTP合同。

1 个答案:

答案 0 :(得分:5)

HTTP请求已在其自己的线程中执行,并且客户端可以异步并行地进行少量请求。所以你不需要开始新的线程。只需像往常一样在主线程中保存/处理文件。只需在客户端进行“异步文件上传”。

此外,只有在处理完输入后才应发送http响应。我的意思是你无法读取输入标题,发出http响应,并继续从浏览器中读取数据。消费输入 - >处理它 - >发送输出,表示HTTP 1 / 1.1协议的工作原理。

如果您需要发送上传的票号,您可以在实际上传之前通过使用两步上传创建它,例如:

  • Ajax GET请求获取票号
  • 发布文件内容和票号(从上一步收到)
  • + ajax GET获取故障单的当前状态,以后随时,async
相关问题