在Spring MVC中使用文件上传和表单数据的RESTful PUT

时间:2012-09-27 08:18:11

标签: java rest spring-mvc put

我正在使用Spring MVC来公开一些RESTful Web服务。其中一个操作在提交表单时调用RESTful PUT操作。

但是,表单不是普通表单,因为它包含文件输入以及常规输入,如文本和复选框。

通过在HiddenHttpMethodFilter中添加web.xml,我已将Spring配置为使用RESTful PUT和DELETE。在我的表单中,我也发送了一个隐藏的_method参数。

所有这一切都适用于DELETE,PUT没有文件上传等。当我尝试使用文件上传和表单数据进行PUT时,它会给我一个405

HTTP Status 405 - Request method 'POST' not supported

我的控制器方法如下所示:

@RequestMapping(value = "/admin/cars/{carId}", method = PUT, headers = "content-type=multipart/form-data")
public String updateCar(@PathVariable("carId") String carId, CarForm form) {
    // save and return the right view.
}

我的HTML表单如下所示:

<form action="<c:url value='/admin/cars/${car.id}'/>" method="POST" enctype="multipart/form-data">
    <input type="hidden" name="_method" value="PUT" />
    <input type="text" name="carName" value="${car.name}" />
    <input type="file" name="photo" />
    <input type="submit" />
</form>

我正在努力实现使用PUT的可行性吗?如果是这样,如何让Spring MVC明白这一点?

3 个答案:

答案 0 :(得分:7)

添加MultipartFilter以在您的web.xml中> HiddenHttpMethodFilter之前启用文件上传(如HiddenHttpMethodFilter API文档see NOTE中所述)。

此外:

  

注意:此过滤器是使用DispatcherServlet的替代方法   MultipartResolver支持,例如对于具有的Web应用程序   自定义Web视图,不使用Spring的Web MVC,或自定义   在Spring MVC DispatcherServlet之前应用的过滤器(例如   HiddenHttpMethodFilter即可。无论如何,这个过滤器不应该   结合servlet特定的多部分分辨率。

(来自MF的文档,强调我的)

此外, MultipartResolver的bean名称必须为filterMultipartResolver才能使MultipartFilter正常运行(或必须通过<init-param>设置)。

修改

正如我在上一篇评论中所预料的那样,CommonsMultipartResolver存在一个问题,默认情况下只支持POST方法。(实际上, isMultipartContent中的方法以POST形式出现即使它是PUT,因为MultipartFilter是在HiddenHttpMethodFilter之前声明的。 as OP notes。)下面是extednded class with slighlty modified static method it uses originally

public class PutAwareCommonsMultipartResolver extends CommonsMultipartResolver {

    private static final String MULTIPART = "multipart/";

    @Override
    public boolean isMultipart(HttpServletRequest request) {
        return request != null && isMultipartContent(request);
    }

    /**
     * Utility method that determines whether the request contains multipart
     * content.
     * 
     * @param request The servlet request to be evaluated. Must be non-null.
     * 
     * @return <code>true</code> if the request is multipart; {@code false}
     * otherwise.
     * 
     * @see ServletFileUpload#isMultipartContent(HttpServletRequest)
     */
    public static final boolean isMultipartContent(HttpServletRequest request) {
        final String method = request.getMethod().toLowerCase();
        if (!method.equals("post") && !method.equals("put")) {
            return false;
        }
        String contentType = request.getContentType();
        if (contentType == null) {
            return false;
        }
        if (contentType.toLowerCase().startsWith(MULTIPART)) {
            return true;
        }
        return false;
    }

}

答案 1 :(得分:2)

实际上,PUT接收二进制流而不是多部分数据。您可以使用org.springframework.web.filter.HiddenHttpMethodFilter使其正常工作。

答案 2 :(得分:1)

如果有人对替代解决方案(使用PUT方法的MultipartResolver)感兴趣,例如要强制执行Restful样式,您可以查看Spring 3.0 FileUpload only with POST?