@@ -62,6 +62,8 @@ public abstract class CommonsFileUploadSupport {
6262
6363 private boolean uploadTempDirSpecified = false ;
6464
65+ private boolean preserveFilename = false ;
66+
6567
6668 /**
6769 * Instantiate a new CommonsFileUploadSupport with its
@@ -168,6 +170,20 @@ protected boolean isUploadTempDirSpecified() {
168170 return this .uploadTempDirSpecified ;
169171 }
170172
173+ /**
174+ * Set whether to preserve the filename as sent by the client, not stripping off
175+ * path information in {@link CommonsMultipartFile#getOriginalFilename()}.
176+ * <p>Default is "false", stripping off path information that may prefix the
177+ * actual filename e.g. from Opera. Switch this to "true" for preserving the
178+ * client-specified filename as-is, including potential path separators.
179+ * @since 4.3.5
180+ * @see MultipartFile#getOriginalFilename()
181+ * @see CommonsMultipartFile#setPreserveFilename(boolean)
182+ */
183+ public void setPreserveFilename (boolean preserveFilename ) {
184+ this .preserveFilename = preserveFilename ;
185+ }
186+
171187
172188 /**
173189 * Factory method for a Commons DiskFileItemFactory instance.
@@ -259,7 +275,7 @@ protected MultipartParsingResult parseFileItems(List<FileItem> fileItems, String
259275 }
260276 else {
261277 // multipart file field
262- CommonsMultipartFile file = new CommonsMultipartFile (fileItem );
278+ CommonsMultipartFile file = createMultipartFile (fileItem );
263279 multipartFiles .add (file .getName (), file );
264280 if (logger .isDebugEnabled ()) {
265281 logger .debug ("Found multipart file [" + file .getName () + "] of size " + file .getSize () +
@@ -271,6 +287,20 @@ protected MultipartParsingResult parseFileItems(List<FileItem> fileItems, String
271287 return new MultipartParsingResult (multipartFiles , multipartParameters , multipartParameterContentTypes );
272288 }
273289
290+ /**
291+ * Create a {@link CommonsMultipartFile} wrapper for the given Commons {@link FileItem}.
292+ * @param fileItem the Commons FileItem to wrap
293+ * @return the corresponding CommonsMultipartFile (potentially a custom subclass)
294+ * @since 4.3.5
295+ * @see #setPreserveFilename(boolean)
296+ * @see CommonsMultipartFile#setPreserveFilename(boolean)
297+ */
298+ protected CommonsMultipartFile createMultipartFile (FileItem fileItem ) {
299+ CommonsMultipartFile multipartFile = new CommonsMultipartFile (fileItem );
300+ multipartFile .setPreserveFilename (this .preserveFilename );
301+ return multipartFile ;
302+ }
303+
274304 /**
275305 * Cleanup the Spring MultipartFiles created during multipart parsing,
276306 * potentially holding temporary data on disk.
@@ -317,6 +347,7 @@ protected static class MultipartParsingResult {
317347
318348 public MultipartParsingResult (MultiValueMap <String , MultipartFile > mpFiles ,
319349 Map <String , String []> mpParams , Map <String , String > mpParamContentTypes ) {
350+
320351 this .multipartFiles = mpFiles ;
321352 this .multipartParameters = mpParams ;
322353 this .multipartParameterContentTypes = mpParamContentTypes ;
0 commit comments