Spring MVC 文件上传 - 由于未提供多部分配置,因此无法处理部分
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37922973/
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
Spring MVC file upload - Unable to process parts as no multi-part configuration has been provided
提问by kbijoch
So I'm a newbie to Spring and I'm trying to get file upload working for my project (I'm using Spring Tool Suite btw.) and when submitting a form all I'm getting is:
所以我是 Spring 的新手,我正在尝试让文件上传为我的项目工作(我正在使用 Spring Tool Suite 顺便说一句。)并且在提交表单时我得到的是:
HTTP Status 500 - Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided
HTTP 状态 500 - 无法解析多部分 servlet 请求;嵌套异常是 java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided
Stack trace from browser:
来自浏览器的堆栈跟踪:
type Exception report message Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided description The server encountered an internal error that prevented it from fulfilling this request. exception org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:100) org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.(StandardMultipartHttpServletRequest.java:78) org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:75) org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:108) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106) root cause java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided org.apache.catalina.connector.Request.parseParts(Request.java:2676) org.apache.catalina.connector.Request.getParts(Request.java:2643) org.apache.catalina.connector.RequestFacade.getParts(RequestFacade.java:1083) org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:85) org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.(StandardMultipartHttpServletRequest.java:78) org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:75) org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:108) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106) note The full stack trace of the root cause is available in the Apache Tomcat/8.0.27 logs.
This is the form tag in jsp:
这是jsp中的表单标签:
<form:form class="form-horizontal" role="form" method="post"
action="newArtist.html" modelAttribute="artist" enctype="multipart/form-data">
Input part:
输入部分:
<div class="form-group">
<div class="col-lg-3">
<label for="photo">Artist photo:</label>
<form:input type="file" id="photo" path="photo"></form:input>
</div>
</div>
Photo is stored in this field in Artist object:
照片存储在艺术家对象中的此字段中:
@Lob
private byte[] photo;
Controller mapping methods:
控制器映射方法:
@RequestMapping(value = "/newArtist", method = RequestMethod.GET)
public String showAddArtistForm(Model model)
{
model.addAttribute("artist", new Artist());
return "newArtist";
}
@RequestMapping(value = "/newArtist", method = RequestMethod.POST)
public String addArtist(@ModelAttribute("artist") @Valid Artist artist, BindingResult result,
@RequestParam("photo") MultipartFile photo) throws IOException
{
if (result.hasErrors())
return "newArtist";
if(photo.getBytes() != null)
artist.setPhoto(photo.getBytes());
artistService.addArtist(artist);
return "redirect:artists.html";
}
Multipart resolver configuration in servlet-context.xml:
servlet-context.xml 中的多部分解析器配置:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10000000"/>
</bean>
Filters in web.xml:
web.xml 中的过滤器:
<filter>
<filter-name>MultipartFilter</filter-name>
<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>MultipartFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Dependencies:
依赖项:
<!-- Apache Commons FileUpload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<!-- Apache Commons IO -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
I also imported Tomcat's config file context.xml to META-INF/context.xml and edited Context tag like so:
我还将 Tomcat 的配置文件 context.xml 导入到 META-INF/context.xml 并编辑了 Context 标记,如下所示:
<Context allowCasualMultipartParsing="true">
Nothing seems to be working, any help will be greatly appreciated.
似乎没有任何工作,任何帮助将不胜感激。
回答by luis-br
Actually you don't need any filter on the web.xml in order to upload your multipart file with Spring MVC. I've the same configuration in my project and it worked (${spring.version} = 4.3.4.RELEASE):
实际上,您不需要在 web.xml 上进行任何过滤器来使用 Spring MVC 上传您的多部分文件。我的项目中有相同的配置并且它有效(${spring.version} = 4.3.4.RELEASE):
POM
聚甲醛
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Apache Commons FileUpload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
<!-- Apache Commons IO -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
HTML
HTML
<form method="POST" enctype="multipart/form-data" action="uploadAction">
<table>
<tr><td>File to upload:</td><td><input type="file" name="file" /></td></tr>
<tr><td></td><td><input type="submit" value="Upload" /></td></tr>
</table>
</form>
Spring context
弹簧上下文
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10000000"/>
</bean>
Spring controller
弹簧控制器
@PostMapping("/uploadAction")
public String handleFileUpload(@RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) {
File out = new File("outputfile.pdf");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(out);
// Writes bytes from the specified byte array to this file output stream
fos.write(file.getBytes());
System.out.println("Upload and writing output file ok");
} catch (FileNotFoundException e) {
System.out.println("File not found" + e);
} catch (IOException ioe) {
System.out.println("Exception while writing file " + ioe);
} finally {
// close the streams using close method
try {
if (fos != null) {
fos.close();
}
} catch (IOException ioe) {
System.out.println("Error while closing stream: " + ioe);
}
//storageService.store(file);
redirectAttributes.addFlashAttribute("message",
"You successfully uploaded " + file.getOriginalFilename() + "!");
return "redirect:/";
}
}
回答by Martín Straus
None of the answers address the issue properly. As per Tomcat documentation, on the configuration of allowCasualMultipartParsing
:
没有一个答案正确地解决了这个问题。根据Tomcat 文档,关于配置allowCasualMultipartParsing
:
Set to true if Tomcat should automatically parse multipart/form-data request bodies when HttpServletRequest.getPart* or HttpServletRequest.getParameter* is called, even when the target servlet isn't marked with the @MultipartConfig annotation (See Servlet Specification 3.0, Section 3.2 for details). Note that any setting other than false causes Tomcat to behave in a way that is not technically spec-compliant. The default is false.
如果在调用 HttpServletRequest.getPart* 或 HttpServletRequest.getParameter* 时 Tomcat 应自动解析 multipart/form-data 请求主体,则设置为 true,即使目标 servlet 未标记为 @MultipartConfig 注释(请参阅 Servlet 规范 3.0,第 3.2 节)详情)。请注意,除 false 之外的任何设置都会导致 Tomcat 以不符合技术规范的方式运行。默认值为假。
So, what's the compliant way? Reading the official JEE 6 tutorialgives a hint. If you want to use a spec-compliant way with Servlet 3 or newer, your servlet must have a MultipartConfig
. You have three choices, depending on how you configure your servlet:
那么,合规的方式是什么?阅读官方JEE 6 教程给出了一个提示。如果您想对 Servlet 3 或更新版本使用符合规范的方式,您的 servlet 必须有一个MultipartConfig
. 根据您配置 servlet 的方式,您有三种选择:
- With programmatic configuration:
context.addServlet(name, servlet).setMultipartConfig(new MultipartConfigElement("your_path")
. - With annotations, annotate the servlet's class with
@javax.servlet.annotation.MultipartConfig
. With XML configuration, add this to the
WEB-INF/web.xml
descriptor, in the section of your servlet:<multipart-config> <location>/tmp</location> <max-file-size>20848820</max-file-size> <max-request-size>418018841</max-request-size> <file-size-threshold>1048576</file-size-threshold> </multipart-config>
- 使用编程配置:
context.addServlet(name, servlet).setMultipartConfig(new MultipartConfigElement("your_path")
. - 使用注释,用
@javax.servlet.annotation.MultipartConfig
. 使用 XML 配置,将其添加到
WEB-INF/web.xml
描述符的 servlet 部分:<multipart-config> <location>/tmp</location> <max-file-size>20848820</max-file-size> <max-request-size>418018841</max-request-size> <file-size-threshold>1048576</file-size-threshold> </multipart-config>
回答by Ramjan Ali
It is straight forward from the exception that no multi-part configuration is found. Though you have provided multipartResolverbean.
从没有找到多部分配置的例外情况来看,这是直接的。尽管您提供了multipartResolverbean。
The problem is that while specifying the MultipartFilter before the Spring Security filter, It tries to get the multipartResolverbean but can't find it. Because it expect the bean name/id as filterMultipartResolverinstead of multipartResolver.
问题是在 Spring Security 过滤器之前指定 MultipartFilter 时,它尝试获取multipartResolverbean 但找不到它。因为它期望 bean 名称/id 为filterMultipartResolver而不是multipartResolver。
Do yourself a favor. Please change the bean configuration like following -
帮自己一个忙。请更改 bean 配置,如下所示 -
<bean id="filterMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10000000"/>
</bean>
回答by izogfif
For those who get the same exception for PUT
method handlers: use POST
instead. PUT
is incompatible with the multi-part.
对于那些在PUT
方法处理程序中遇到相同异常的人:POST
改为使用。PUT
与多部分不兼容。
More details can be found in the respective answer
更多细节可以在相应的答案中找到
回答by susan097
Add In your config file as:
在您的配置文件中添加:
@Bean(name = "multipartResolver")
public CommonsMultipartResolver CanBeAnyName() {
//configuration
}
回答by cralfaro
I have something similar, but what i did is just send a file without mapping it with any attribute in my model, in your case i would modify this:
我有类似的东西,但我所做的只是发送一个文件,而不将它与我的模型中的任何属性进行映射,在你的情况下,我会修改这个:
<div class="form-group">
<div class="col-lg-3">
<label for="photo">Artist photo:</label>
<input type="file" id="photo" name="file"/>
</div>
</div>
In your controller
在您的控制器中
@RequestMapping(value = "/newArtist", method = RequestMethod.POST)
public String addArtist(@ModelAttribute("artist") @Valid Artist artist, BindingResult result,
@RequestParam("file") MultipartFile file) throws IOException
//Here read the file and store the bytes into your photo attribute
...
回答by ElMurxOr
Had the same issue in a Spring Boot application, this exceptions occur several times:
在 Spring Boot 应用程序中遇到了同样的问题,这个异常多次发生:
- org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is
- java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field multipartFile exceeds its maximum permitted size of 1048576 bytes
- org.springframework.web.multipart.MultipartException:无法解析多部分 servlet 请求;嵌套异常是
- java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: 字段 multipartFile 超过其最大允许大小 1048576 字节
org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field multipartFile exceeds its maximum permitted size of 1048576 bytes.
org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException:字段 multipartFile 超过其最大允许大小 1048576 字节。
Get rid of the tomcat exception with this, with copy catting from http://www.mkyong.com/spring-boot/spring-boot-file-upload-example/
用这个摆脱 tomcat 异常,从http://www.mkyong.com/spring-boot/spring-boot-file-upload-example/复制 catting
Tomcat large file upload connection reset. Need to let {@link #containerCustomizer()} work properly, other wise exception will occur several times, RequestMapping for uploadError will fail.
Tomcat 大文件上传连接重置。需要让 {@link #containerCustomizer()} 正常工作,否则会多次发生异常,上传错误的 RequestMapping 将失败。
@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbedded() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> {
if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol<?>)) {
//-1 means unlimited
((AbstractHttp11Protocol<?>) connector.getProtocolHandler()).setMaxSwallowSize(-1);
}
});
return tomcat;
}
回答by Yachin K
If you are using Tomcat 8.
Configure the following in Tomcat's conf/context.xml
如果你使用的是 Tomcat 8.
在 Tomcat 的 conf/context.xml 中配置以下内容
- Add allowCasualMultipartParsing="true" attribute to context node
- Add <Resources cachingAllowed="true" cacheMaxSize="100000" /> inside context node
- 将 allowCasualMultipartParsing="true" 属性添加到上下文节点
- 在上下文节点中添加 <Resources cachingAllowed="true" cacheMaxSize="100000" />