java Spring MVC中带有文件上传和表单数据的RESTful PUT

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12616928/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 09:34:35  来源:igfitidea点击:

RESTful PUT with file upload and form data in Spring MVC

javarestspring-mvcput

提问by adarshr

I am using Spring MVC to expose some RESTful web services. One of the operations calls for a RESTful PUT operation when a form is submitted.

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

However, the form is no ordinary form in that it contains a file input along with regular inputs such as text and checkboxes.

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

I have configured Spring to work with RESTful PUT and DELETE by adding the HiddenHttpMethodFilterin the web.xml. In my forms, i have a hidden _methodparameter being sent as well.

我已经通过HiddenHttpMethodFilterweb.xml. 在我的表单中,我也_method发送了一个隐藏参数。

All this works fine for DELETE, PUT without file upload, etc. When I try to do a PUT with file upload and form data, it gives me a 405.

所有这些都适用于 DELETE、不上传文件的 PUT 等。当我尝试使用文件上传和表单数据执行 PUT 时,它给了我一个405.

HTTP Status 405 - Request method 'POST' not supported

My controller method looks like this:

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

@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.
}

My HTML form looks like this:

我的 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>

Is what I am trying to achieve doable at all using PUT? If so, how to make Spring MVC understand that?

我试图使用 PUT 实现的目标是可行的吗?如果是这样,如何让 Spring MVC 理解这一点?

回答by Xaerxess

Add MultipartFilterto enable file uploads beforeHiddenHttpMethodFilterin your web.xml (as written in HiddenHttpMethodFilterAPI docs, see NOTE).

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

Also:

还:

Note: This filter is an alternative to using DispatcherServlet's MultipartResolversupport, for example for web applications with custom web views which do not use Spring's web MVC, or for custom filters applied before a Spring MVC DispatcherServlet(e.g. HiddenHttpMethodFilter). In any case, this filter should not be combined with servlet-specific multipart resolution.

注:该过滤器是使用替代DispatcherServletMultipartResolver支持,例如用于与不使用Spring的web MVC,自定义Web视图的Web应用程序或为Spring MVC的前应用自定义过滤器DispatcherServlet(如 HiddenHttpMethodFilter。无论如何,此过滤器不应与特定于 servlet 的多部分解析结合使用。

(from MF's docs, emphasis mine)

(来自 MF 的文档,重点是我的)

Also, MultipartResolver's bean name must be filterMultipartResolverin order to MultipartFilter run properly(or must be set via <init-param>).

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

EDIT:

编辑:

As I expected in my last comment, there's an issue with CommonsMultipartResolverwhich supports only POST method by default.(Actually, The method in the isMultipartContent comes in as POST even though it is a PUT as the MultipartFilter is declared before the HiddenHttpMethodFilter.as OP notes.) Below is extednded class with slighlty modified static method it uses originally:

正如我在上一条评论中所预期的那样,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;
    }

}

回答by Michael-O

Actually, PUTreceives a binary stream and not multipart data. You can use org.springframework.web.filter.HiddenHttpMethodFilterto make it work.

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

回答by Jean-Christophe

If anyone is interested in an alternative solution (MultipartResolver with PUT method), to enforce Restful style for instance, you may have a look at Spring 3.0 FileUpload only with POST?.

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