001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.multipart.support; 018 019import java.io.IOException; 020 021import javax.servlet.FilterChain; 022import javax.servlet.ServletException; 023import javax.servlet.http.HttpServletRequest; 024import javax.servlet.http.HttpServletResponse; 025 026import org.springframework.web.context.WebApplicationContext; 027import org.springframework.web.context.support.WebApplicationContextUtils; 028import org.springframework.web.filter.OncePerRequestFilter; 029import org.springframework.web.multipart.MultipartHttpServletRequest; 030import org.springframework.web.multipart.MultipartResolver; 031 032/** 033 * Servlet Filter that resolves multipart requests via a {@link MultipartResolver}. 034 * in the root web application context. 035 * 036 * <p>Looks up the MultipartResolver in Spring's root web application context. 037 * Supports a "multipartResolverBeanName" filter init-param in {@code web.xml}; 038 * the default bean name is "filterMultipartResolver". 039 * 040 * <p>If no MultipartResolver bean is found, this filter falls back to a default 041 * MultipartResolver: {@link StandardServletMultipartResolver} for Servlet 3.0, 042 * based on a multipart-config section in {@code web.xml}. 043 * Note however that at present the Servlet specification only defines how to 044 * enable multipart configuration on a Servlet and as a result multipart request 045 * processing is likely not possible in a Filter unless the Servlet container 046 * provides a workaround such as Tomcat's "allowCasualMultipartParsing" property. 047 * 048 * <p>MultipartResolver lookup is customizable: Override this filter's 049 * {@code lookupMultipartResolver} method to use a custom MultipartResolver 050 * instance, for example if not using a Spring web application context. 051 * Note that the lookup method should not create a new MultipartResolver instance 052 * for each call but rather return a reference to a pre-built instance. 053 * 054 * <p>Note: This filter is an <b>alternative</b> to using DispatcherServlet's 055 * MultipartResolver support, for example for web applications with custom web views 056 * which do not use Spring's web MVC, or for custom filters applied before a Spring MVC 057 * DispatcherServlet (e.g. {@link org.springframework.web.filter.HiddenHttpMethodFilter}). 058 * In any case, this filter should not be combined with servlet-specific multipart resolution. 059 * 060 * @author Juergen Hoeller 061 * @since 08.10.2003 062 * @see #setMultipartResolverBeanName 063 * @see #lookupMultipartResolver 064 * @see org.springframework.web.multipart.MultipartResolver 065 * @see org.springframework.web.servlet.DispatcherServlet 066 */ 067public class MultipartFilter extends OncePerRequestFilter { 068 069 /** 070 * The default name for the multipart resolver bean. 071 */ 072 public static final String DEFAULT_MULTIPART_RESOLVER_BEAN_NAME = "filterMultipartResolver"; 073 074 private final MultipartResolver defaultMultipartResolver = new StandardServletMultipartResolver(); 075 076 private String multipartResolverBeanName = DEFAULT_MULTIPART_RESOLVER_BEAN_NAME; 077 078 079 /** 080 * Set the bean name of the MultipartResolver to fetch from Spring's 081 * root application context. Default is "filterMultipartResolver". 082 */ 083 public void setMultipartResolverBeanName(String multipartResolverBeanName) { 084 this.multipartResolverBeanName = multipartResolverBeanName; 085 } 086 087 /** 088 * Return the bean name of the MultipartResolver to fetch from Spring's 089 * root application context. 090 */ 091 protected String getMultipartResolverBeanName() { 092 return this.multipartResolverBeanName; 093 } 094 095 096 /** 097 * Check for a multipart request via this filter's MultipartResolver, 098 * and wrap the original request with a MultipartHttpServletRequest if appropriate. 099 * <p>All later elements in the filter chain, most importantly servlets, benefit 100 * from proper parameter extraction in the multipart case, and are able to cast to 101 * MultipartHttpServletRequest if they need to. 102 */ 103 @Override 104 protected void doFilterInternal( 105 HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 106 throws ServletException, IOException { 107 108 MultipartResolver multipartResolver = lookupMultipartResolver(request); 109 110 HttpServletRequest processedRequest = request; 111 if (multipartResolver.isMultipart(processedRequest)) { 112 if (logger.isTraceEnabled()) { 113 logger.trace("Resolving multipart request"); 114 } 115 processedRequest = multipartResolver.resolveMultipart(processedRequest); 116 } 117 else { 118 // A regular request... 119 if (logger.isTraceEnabled()) { 120 logger.trace("Not a multipart request"); 121 } 122 } 123 124 try { 125 filterChain.doFilter(processedRequest, response); 126 } 127 finally { 128 if (processedRequest instanceof MultipartHttpServletRequest) { 129 multipartResolver.cleanupMultipart((MultipartHttpServletRequest) processedRequest); 130 } 131 } 132 } 133 134 /** 135 * Look up the MultipartResolver that this filter should use, 136 * taking the current HTTP request as argument. 137 * <p>The default implementation delegates to the {@code lookupMultipartResolver} 138 * without arguments. 139 * @return the MultipartResolver to use 140 * @see #lookupMultipartResolver() 141 */ 142 protected MultipartResolver lookupMultipartResolver(HttpServletRequest request) { 143 return lookupMultipartResolver(); 144 } 145 146 /** 147 * Look for a MultipartResolver bean in the root web application context. 148 * Supports a "multipartResolverBeanName" filter init param; the default 149 * bean name is "filterMultipartResolver". 150 * <p>This can be overridden to use a custom MultipartResolver instance, 151 * for example if not using a Spring web application context. 152 * @return the MultipartResolver instance 153 */ 154 protected MultipartResolver lookupMultipartResolver() { 155 WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); 156 String beanName = getMultipartResolverBeanName(); 157 if (wac != null && wac.containsBean(beanName)) { 158 if (logger.isDebugEnabled()) { 159 logger.debug("Using MultipartResolver '" + beanName + "' for MultipartFilter"); 160 } 161 return wac.getBean(beanName, MultipartResolver.class); 162 } 163 else { 164 return this.defaultMultipartResolver; 165 } 166 } 167 168}