Support multipart filename with charset

StandardMultipartHttpServletRequest now supports filenames with
charset information.

Issue: SPR-13319
This commit is contained in:
Rossen Stoyanchev
2015-08-25 20:52:30 -04:00
parent 4314da922a
commit 1a9e42b49d
2 changed files with 94 additions and 12 deletions

View File

@@ -20,6 +20,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -44,6 +45,7 @@ import org.springframework.web.multipart.MultipartFile;
* methods - without any custom processing on our side.
*
* @author Juergen Hoeller
* @author Rossen Stoyanchev
* @since 3.1
*/
public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpServletRequest {
@@ -52,6 +54,11 @@ public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpSe
private static final String FILENAME_KEY = "filename=";
private static final String FILENAME_WITH_CHARSET_KEY = "filename*=";
private static final Charset US_ASCII = Charset.forName("us-ascii");
private Set<String> multipartParameterNames;
@@ -86,7 +93,11 @@ public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpSe
this.multipartParameterNames = new LinkedHashSet<String>(parts.size());
MultiValueMap<String, MultipartFile> files = new LinkedMultiValueMap<String, MultipartFile>(parts.size());
for (Part part : parts) {
String filename = extractFilename(part.getHeader(CONTENT_DISPOSITION));
String disposition = part.getHeader(CONTENT_DISPOSITION);
String filename = extractFilename(disposition);
if (filename == null) {
filename = extractFilenameWithCharset(disposition);
}
if (filename != null) {
files.add(part.getName(), new StandardMultipartFile(part, filename));
}
@@ -102,15 +113,18 @@ public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpSe
}
private String extractFilename(String contentDisposition) {
return extractFilename(contentDisposition, FILENAME_KEY);
}
private String extractFilename(String contentDisposition, String key) {
if (contentDisposition == null) {
return null;
}
// TODO: can only handle the typical case at the moment
int startIndex = contentDisposition.indexOf(FILENAME_KEY);
int startIndex = contentDisposition.indexOf(key);
if (startIndex == -1) {
return null;
}
String filename = contentDisposition.substring(startIndex + FILENAME_KEY.length());
String filename = contentDisposition.substring(startIndex + key.length());
if (filename.startsWith("\"")) {
int endIndex = filename.indexOf("\"", 1);
if (endIndex != -1) {
@@ -126,6 +140,33 @@ public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpSe
return filename;
}
private String extractFilenameWithCharset(String contentDisposition) {
String filename = extractFilename(contentDisposition, FILENAME_WITH_CHARSET_KEY);
if (filename == null) {
return null;
}
int index = filename.indexOf("'");
if (index != -1) {
Charset charset = null;
try {
charset = Charset.forName(filename.substring(0, index));
}
catch (IllegalArgumentException ex) {
// ignore
}
filename = filename.substring(index + 1);
// Skip language information..
index = filename.indexOf("'");
if (index != -1) {
filename = filename.substring(index + 1);
}
if (charset != null) {
filename = new String(filename.getBytes(US_ASCII), charset);
}
}
return filename;
}
@Override
protected void initializeMultipart() {