7

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

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

我通过HiddenHttpMethodFilterweb.xml. 在我的表单中,我还_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 理解这一点?

4

3 回答 3

9

在您的 web.xml之前添加MultipartFilter以启用文件上传(如API 文档中所写,请参阅 NOTE)。 HiddenHttpMethodFilterHiddenHttpMethodFilter

还:

注意:此过滤器是使用DispatcherServlet' MultipartResolver支持的替代方案,例如对于具有不使用 Spring 的 Web MVC 的自定义 Web 视图的 Web 应用程序,或用于在 Spring MVC 之前应用的自定义过滤器DispatcherServlet(例如 HiddenHttpMethodFilter。在任何情况下,此过滤器都不应与特定于 servlet 的多部分解析结合使用。

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

此外,MultipartResolver的 bean 名称必须是filterMultipartResolverMultipartFilter 正常运行(或必须通过 设置<init-param>)。

编辑:

正如我在上一条评论中所预料的那样,CommonsMultipartResolver默认情况下仅支持 POST 方法存在一个问题。(实际上,isMultipartContent 中的方法以 POST 形式出现,即使它是 PUT,因为 MultipartFilter 是在 HiddenHttpMethodFilter 之前声明的。 正如 OP 注释。)下面是扩展类,它最初使用的静态方法经过轻微修改:

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;
    }

}
于 2012-09-27T08:32:29.680 回答
2

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

于 2012-09-27T08:25:19.030 回答
1

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

于 2015-11-11T19:19:11.560 回答