Support writing multipart non-ASCII file names
Issue: SPR-12108
This commit is contained in:
parent
6cbe1433e2
commit
9be0cf21e5
|
|
@ -684,6 +684,7 @@ project("spring-web") {
|
|||
optional("log4j:log4j:1.2.17")
|
||||
optional("com.googlecode.protobuf-java-format:protobuf-java-format:1.2")
|
||||
optional("com.google.protobuf:protobuf-java:${protobufVersion}")
|
||||
optional("javax.mail:javax.mail-api:1.5.2")
|
||||
testCompile(project(":spring-context-support")) // for JafMediaTypeFactory
|
||||
testCompile("xmlunit:xmlunit:1.5")
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ import org.springframework.util.MultiValueMap;
|
|||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.mail.internet.MimeUtility;
|
||||
|
||||
/**
|
||||
* Implementation of {@link HttpMessageConverter} to read and write 'normal' HTML
|
||||
* forms and also to write (but not read) multipart data (e.g. file uploads).
|
||||
|
|
@ -92,6 +94,8 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
|
|||
|
||||
private Charset charset = Charset.forName("UTF-8");
|
||||
|
||||
private Charset multipartCharset;
|
||||
|
||||
private List<MediaType> supportedMediaTypes = new ArrayList<MediaType>();
|
||||
|
||||
private List<HttpMessageConverter<?>> partConverters = new ArrayList<HttpMessageConverter<?>>();
|
||||
|
|
@ -118,6 +122,18 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
|
|||
this.charset = charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the character set to use when writing multipart data to encode file
|
||||
* names. Encoding is based on the encoded-word syntax defined in RFC 2047
|
||||
* and relies on the MimeUtility class from "javax.mail-api".
|
||||
* <p>If not set file names will be encoded as US-ASCII.
|
||||
* @param multipartCharset the charset to use
|
||||
* @see <a href="http://en.wikipedia.org/wiki/MIME#Encoded-Word">Encoded-Word</a>
|
||||
*/
|
||||
public void setMultipartCharset(Charset multipartCharset) {
|
||||
this.multipartCharset = multipartCharset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the list of {@link MediaType} objects supported by this converter.
|
||||
*/
|
||||
|
|
@ -374,7 +390,17 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
|
|||
protected String getFilename(Object part) {
|
||||
if (part instanceof Resource) {
|
||||
Resource resource = (Resource) part;
|
||||
return resource.getFilename();
|
||||
String filename = resource.getFilename();
|
||||
if (multipartCharset != null) {
|
||||
try {
|
||||
filename = MimeUtility.encodeText(filename, multipartCharset.name(), null);
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
// should not happen
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -116,6 +116,17 @@ public class FormHttpMessageConverterTests {
|
|||
|
||||
Resource logo = new ClassPathResource("/org/springframework/http/converter/logo.jpg");
|
||||
parts.add("logo", logo);
|
||||
|
||||
// SPR-12108
|
||||
|
||||
Resource utf8 = new ClassPathResource("/org/springframework/http/converter/logo.jpg") {
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return "Hall\u00F6le.jpg";
|
||||
}
|
||||
};
|
||||
parts.add("utf8", utf8);
|
||||
|
||||
Source xml = new StreamSource(new StringReader("<root><child/></root>"));
|
||||
HttpHeaders entityHeaders = new HttpHeaders();
|
||||
entityHeaders.setContentType(MediaType.TEXT_XML);
|
||||
|
|
@ -123,6 +134,7 @@ public class FormHttpMessageConverterTests {
|
|||
parts.add("xml", entity);
|
||||
|
||||
MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
|
||||
converter.setMultipartCharset(Charset.forName("UTF-8"));
|
||||
converter.write(parts, MediaType.MULTIPART_FORM_DATA, outputMessage);
|
||||
|
||||
final MediaType contentType = outputMessage.getHeaders().getContentType();
|
||||
|
|
@ -132,7 +144,7 @@ public class FormHttpMessageConverterTests {
|
|||
FileItemFactory fileItemFactory = new DiskFileItemFactory();
|
||||
FileUpload fileUpload = new FileUpload(fileItemFactory);
|
||||
List<FileItem> items = fileUpload.parseRequest(new MockHttpOutputMessageRequestContext(outputMessage));
|
||||
assertEquals(5, items.size());
|
||||
assertEquals(6, items.size());
|
||||
FileItem item = items.get(0);
|
||||
assertTrue(item.isFormField());
|
||||
assertEquals("name 1", item.getFieldName());
|
||||
|
|
@ -156,6 +168,13 @@ public class FormHttpMessageConverterTests {
|
|||
assertEquals(logo.getFile().length(), item.getSize());
|
||||
|
||||
item = items.get(4);
|
||||
assertFalse(item.isFormField());
|
||||
assertEquals("utf8", item.getFieldName());
|
||||
assertEquals("Hall\u00F6le.jpg", item.getName());
|
||||
assertEquals("image/jpeg", item.getContentType());
|
||||
assertEquals(logo.getFile().length(), item.getSize());
|
||||
|
||||
item = items.get(5);
|
||||
assertEquals("xml", item.getFieldName());
|
||||
assertEquals("text/xml", item.getContentType());
|
||||
verify(outputMessage.getBody(), never()).close();
|
||||
|
|
|
|||
Loading…
Reference in New Issue