Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change the character encoding for Servlet 3.0 Spring MVC multipart upload forms?

I have a pretty simple JSP/Servlet 3.0/Spring MVC 3.1 application.

On one of my pages, I have multiple forms. One of these forms allows the user to upload a file and it is thus configured with enctype="multipart/form-data". I configured the multipart upload in the web.xml file with the multipart-config element that is available since Servlet 3.0, combined with <bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"/> in my spring configuration.

I also have Spring's org.springframework.web.filter.CharacterEncodingFilter configured.

The problem I have is that I cannot find a way to set the StandardServletMultipartResolver's default encoding to UTF-8, which often causes the contents of the textfields in the multipart form to be all garbled up.

Is there any way to fix this?

Thanks in advance.

web.xml config:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                  http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>foo-web</display-name>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        WEB-INF\applicationContext.xml
    </param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name>foo</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>0</load-on-startup>
    <multipart-config>
        <max-file-size>52428800</max-file-size>
        <file-size-threshold>5242880</file-size-threshold>
    </multipart-config>
</servlet>
<servlet-mapping>
    <servlet-name>foo</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
    <welcome-file>login</welcome-file>
</welcome-file-list>

like image 460
Mopper Avatar asked Jan 29 '12 17:01

Mopper


2 Answers

Since I found no way to set the default encoding using the StandardMultipartResolver, I dumped the servlet 3.0 config and went for the good old CommonsMultipartResolver.

I configured it like this in my spring servlet context:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- one of the properties available; the maximum file size in bytes -->
    <property name="maxUploadSize" value="157286400" />
    <property name="maxInMemorySize" value="5242880"/>
    <property name="defaultEncoding" value="utf-8"/>
</bean>

In the end, there isn't much difference, since under the hood of the StandardMultipartResolver, it just delegates to CommonsMultipartResolver.

I actually find the servlet 3.0 approach more troublesome, since it requires configuration in both web.xml and your servlet context, and you lose the ability to set the default encoding.

like image 22
Mopper Avatar answered Oct 08 '22 16:10

Mopper


I also had the problem with encoding when using the Servlet 3 API. After some research, I have found that there is a bug in Tomcat 7 which makes the parameters not to be read with the correct encoding under certain conditions. There is a work-around. First, you need to tell which encoding it actually is (if it is not default iso-8859-1):

request.setCharacterEncoding("UTF-8");

This is basically what the CharacterEncodingFilter in Spring does. Nothing strange so far. Now the trick. Call this:

request.getParameterNames()

Make sure this method is invoked before getParts(). If you are using Spring I guess you need to do this in a filter before the request ends up in Spring. The order which the methods are invoked are crucial.

Update: The Tomcat bug has been fixed in 7.0.41 onwards, so if you use a recent version of Tomcat you only need to set the character encoding to get correct result.

like image 61
holmis83 Avatar answered Oct 08 '22 18:10

holmis83