diff --git a/spring-web/src/main/java/org/springframework/web/multipart/MultipartFile.java b/spring-web/src/main/java/org/springframework/web/multipart/MultipartFile.java index 6097bd39ab9..f5674104c15 100644 --- a/spring-web/src/main/java/org/springframework/web/multipart/MultipartFile.java +++ b/spring-web/src/main/java/org/springframework/web/multipart/MultipartFile.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,9 +48,8 @@ public interface MultipartFile extends InputStreamSource { * Return the original filename in the client's filesystem. *

This may contain path information depending on the browser used, * but it typically will not with any other than Opera. - * @return the original filename, or the empty String if no file - * has been chosen in the multipart form, or {@code null} - * if not defined or not available + * @return the original filename, or the empty String if no file has been chosen + * in the multipart form, or {@code null} if not defined or not available */ String getOriginalFilename(); diff --git a/spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsFileUploadSupport.java b/spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsFileUploadSupport.java index e2339b58707..2bafb378dea 100644 --- a/spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsFileUploadSupport.java +++ b/spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsFileUploadSupport.java @@ -62,6 +62,8 @@ public abstract class CommonsFileUploadSupport { private boolean uploadTempDirSpecified = false; + private boolean preserveFilename = false; + /** * Instantiate a new CommonsFileUploadSupport with its @@ -168,6 +170,20 @@ public abstract class CommonsFileUploadSupport { return this.uploadTempDirSpecified; } + /** + * Set whether to preserve the filename as sent by the client, not stripping off + * path information in {@link CommonsMultipartFile#getOriginalFilename()}. + *

Default is "false", stripping off path information that may prefix the + * actual filename e.g. from Opera. Switch this to "true" for preserving the + * client-specified filename as-is, including potential path separators. + * @since 4.3.5 + * @see MultipartFile#getOriginalFilename() + * @see CommonsMultipartFile#setPreserveFilename(boolean) + */ + public void setPreserveFilename(boolean preserveFilename) { + this.preserveFilename = preserveFilename; + } + /** * Factory method for a Commons DiskFileItemFactory instance. @@ -259,7 +275,7 @@ public abstract class CommonsFileUploadSupport { } else { // multipart file field - CommonsMultipartFile file = new CommonsMultipartFile(fileItem); + CommonsMultipartFile file = createMultipartFile(fileItem); multipartFiles.add(file.getName(), file); if (logger.isDebugEnabled()) { logger.debug("Found multipart file [" + file.getName() + "] of size " + file.getSize() + @@ -271,6 +287,20 @@ public abstract class CommonsFileUploadSupport { return new MultipartParsingResult(multipartFiles, multipartParameters, multipartParameterContentTypes); } + /** + * Create a {@link CommonsMultipartFile} wrapper for the given Commons {@link FileItem}. + * @param fileItem the Commons FileItem to wrap + * @return the corresponding CommonsMultipartFile (potentially a custom subclass) + * @since 4.3.5 + * @see #setPreserveFilename(boolean) + * @see CommonsMultipartFile#setPreserveFilename(boolean) + */ + protected CommonsMultipartFile createMultipartFile(FileItem fileItem) { + CommonsMultipartFile multipartFile = new CommonsMultipartFile(fileItem); + multipartFile.setPreserveFilename(this.preserveFilename); + return multipartFile; + } + /** * Cleanup the Spring MultipartFiles created during multipart parsing, * potentially holding temporary data on disk. @@ -317,6 +347,7 @@ public abstract class CommonsFileUploadSupport { public MultipartParsingResult(MultiValueMap mpFiles, Map mpParams, Map mpParamContentTypes) { + this.multipartFiles = mpFiles; this.multipartParameters = mpParams; this.multipartParameterContentTypes = mpParamContentTypes; diff --git a/spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsMultipartFile.java b/spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsMultipartFile.java index ac7d9f11f49..0915b07d9d2 100644 --- a/spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsMultipartFile.java +++ b/spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsMultipartFile.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,6 +47,8 @@ public class CommonsMultipartFile implements MultipartFile, Serializable { private final long size; + private boolean preserveFilename = false; + /** * Create an instance wrapping the given FileItem. @@ -66,6 +68,21 @@ public class CommonsMultipartFile implements MultipartFile, Serializable { return this.fileItem; } + /** + * Set whether to preserve the filename as sent by the client, not stripping off + * path information in {@link CommonsMultipartFile#getOriginalFilename()}. + *

Default is "false", stripping off path information that may prefix the + * actual filename e.g. from Opera. Switch this to "true" for preserving the + * client-specified filename as-is, including potential path separators. + * @since 4.3.5 + * @see #getOriginalFilename() + * @see CommonsMultipartResolver#setPreserveFilename(boolean) + */ + public void setPreserveFilename(boolean preserveFilename) { + this.preserveFilename = preserveFilename; + } + + @Override public String getName() { return this.fileItem.getFieldName(); @@ -78,6 +95,10 @@ public class CommonsMultipartFile implements MultipartFile, Serializable { // Should never happen. return ""; } + if (this.preserveFilename) { + // Do not try to strip off a path... + return filename; + } // Check for Unix-style path int unixSep = filename.lastIndexOf("/");