11

这就是我正在做的事情。我想通过 Ajax 将多部分文件上传到我的 Spring Web 应用程序。当服务器收到 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() 被调用时,它将开始解析和初始化多部分文件。这会导致调用“request.getFile("theFile");”之间的竞争条件。在 runnable 和 cleanupMultipart() 调用中最终导致异常。

有人有想法么?我是否通过想要进行后端异步文件处理来打破某种 HTTP 合同。

4

1 回答 1

8

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

此外,您应该仅在处理完输入后发送 http 响应。我的意思是您无法读取输入标头、做出 http 响应并继续从浏览器读取数据。使用输入 -> 处理它 -> 发送输出,HTTP 1/1.1 协议是如何工作的。

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

  • Ajax GET 请求获取票号
  • POST 文件内容和票号(从上一步收到)
  • + ajax GET 获取票证的当前状态,稍后随时异步
于 2012-06-13T05:53:24.960 回答