@@ -68,6 +68,8 @@ public abstract class CommonsFileUploadSupport {
6868
6969 private boolean uploadTempDirSpecified = false ;
7070
71+ private boolean preserveFilename = false ;
72+
7173
7274 /**
7375 * Instantiate a new CommonsFileUploadSupport with its
@@ -174,6 +176,20 @@ protected boolean isUploadTempDirSpecified() {
174176 return this .uploadTempDirSpecified ;
175177 }
176178
179+ /**
180+ * Set whether to preserve the filename as sent by the client, not stripping off
181+ * path information in {@link CommonsMultipartFile#getOriginalFilename()}.
182+ * <p>Default is "false", stripping off path information that may prefix the
183+ * actual filename e.g. from Opera. Switch this to "true" for preserving the
184+ * client-specified filename as-is, including potential path separators.
185+ * @since 4.3.5
186+ * @see MultipartFile#getOriginalFilename()
187+ * @see CommonsMultipartFile#setPreserveFilename(boolean)
188+ */
189+ public void setPreserveFilename (boolean preserveFilename ) {
190+ this .preserveFilename = preserveFilename ;
191+ }
192+
177193
178194 /**
179195 * Factory method for a Commons DiskFileItemFactory instance.
@@ -265,7 +281,7 @@ protected MultipartParsingResult parseFileItems(List<FileItem> fileItems, String
265281 }
266282 else {
267283 // multipart file field
268- CommonsMultipartFile file = new CommonsMultipartFile (fileItem );
284+ CommonsMultipartFile file = createMultipartFile (fileItem );
269285 multipartFiles .add (file .getName (), file );
270286 if (logger .isDebugEnabled ()) {
271287 logger .debug ("Found multipart file [" + file .getName () + "] of size " + file .getSize () +
@@ -277,6 +293,20 @@ protected MultipartParsingResult parseFileItems(List<FileItem> fileItems, String
277293 return new MultipartParsingResult (multipartFiles , multipartParameters , multipartParameterContentTypes );
278294 }
279295
296+ /**
297+ * Create a {@link CommonsMultipartFile} wrapper for the given Commons {@link FileItem}.
298+ * @param fileItem the Commons FileItem to wrap
299+ * @return the corresponding CommonsMultipartFile (potentially a custom subclass)
300+ * @since 4.3.5
301+ * @see #setPreserveFilename(boolean)
302+ * @see CommonsMultipartFile#setPreserveFilename(boolean)
303+ */
304+ protected CommonsMultipartFile createMultipartFile (FileItem fileItem ) {
305+ CommonsMultipartFile multipartFile = new CommonsMultipartFile (fileItem );
306+ multipartFile .setPreserveFilename (this .preserveFilename );
307+ return multipartFile ;
308+ }
309+
280310 /**
281311 * Cleanup the Spring MultipartFiles created during multipart parsing,
282312 * potentially holding temporary data on disk.
@@ -323,6 +353,7 @@ protected static class MultipartParsingResult {
323353
324354 public MultipartParsingResult (MultiValueMap <String , MultipartFile > mpFiles ,
325355 Map <String , String []> mpParams , Map <String , String > mpParamContentTypes ) {
356+
326357 this .multipartFiles = mpFiles ;
327358 this .multipartParameters = mpParams ;
328359 this .multipartParameterContentTypes = mpParamContentTypes ;
0 commit comments