Skip to content

Commit 5115c61

Browse files
committed
CommonsMultipartFile.getOriginalFilename() can be configured to preserve header-specified filename as-is
Issue: SPR-14613 (cherry picked from commit aa29495)
1 parent 54c7a9e commit 5115c61

File tree

3 files changed

+57
-6
lines changed

3 files changed

+57
-6
lines changed

spring-web/src/main/java/org/springframework/web/multipart/MultipartFile.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -48,9 +48,8 @@ public interface MultipartFile extends InputStreamSource {
4848
* Return the original filename in the client's filesystem.
4949
* <p>This may contain path information depending on the browser used,
5050
* but it typically will not with any other than Opera.
51-
* @return the original filename, or the empty String if no file
52-
* has been chosen in the multipart form, or {@code null}
53-
* if not defined or not available
51+
* @return the original filename, or the empty String if no file has been chosen
52+
* in the multipart form, or {@code null} if not defined or not available
5453
*/
5554
String getOriginalFilename();
5655

spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsFileUploadSupport.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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;

spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsMultipartFile.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -47,6 +47,8 @@ public class CommonsMultipartFile implements MultipartFile, Serializable {
4747

4848
private final long size;
4949

50+
private boolean preserveFilename = false;
51+
5052

5153
/**
5254
* Create an instance wrapping the given FileItem.
@@ -66,6 +68,21 @@ public final FileItem getFileItem() {
6668
return this.fileItem;
6769
}
6870

71+
/**
72+
* Set whether to preserve the filename as sent by the client, not stripping off
73+
* path information in {@link CommonsMultipartFile#getOriginalFilename()}.
74+
* <p>Default is "false", stripping off path information that may prefix the
75+
* actual filename e.g. from Opera. Switch this to "true" for preserving the
76+
* client-specified filename as-is, including potential path separators.
77+
* @since 4.3.5
78+
* @see #getOriginalFilename()
79+
* @see CommonsMultipartResolver#setPreserveFilename(boolean)
80+
*/
81+
public void setPreserveFilename(boolean preserveFilename) {
82+
this.preserveFilename = preserveFilename;
83+
}
84+
85+
6986
@Override
7087
public String getName() {
7188
return this.fileItem.getFieldName();
@@ -78,6 +95,10 @@ public String getOriginalFilename() {
7895
// Should never happen.
7996
return "";
8097
}
98+
if (this.preserveFilename) {
99+
// Do not try to strip off a path...
100+
return filename;
101+
}
81102

82103
// Check for Unix-style path
83104
int unixSep = filename.lastIndexOf("/");

0 commit comments

Comments
 (0)