diff --git a/spring-web/src/main/java/org/springframework/http/converter/BufferedImageHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/BufferedImageHttpMessageConverter.java index 7df72035e33..12dd772687b 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/BufferedImageHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/BufferedImageHttpMessageConverter.java @@ -38,9 +38,11 @@ import javax.imageio.stream.ImageOutputStream; import javax.imageio.stream.MemoryCacheImageInputStream; import javax.imageio.stream.MemoryCacheImageOutputStream; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; +import org.springframework.http.StreamingHttpOutputMessage; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -203,7 +205,30 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter imageWriters = ImageIO.getImageWritersByMIMEType(contentType.toString()); if (imageWriters.hasNext()) { imageWriter = imageWriters.next(); ImageWriteParam iwp = imageWriter.getDefaultWriteParam(); process(iwp); + imageOutputStream = createImageOutputStream(body); imageWriter.setOutput(imageOutputStream); imageWriter.write(null, new IIOImage(image, null, null), iwp); } diff --git a/spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java index 919407d9f46..92d21595111 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java @@ -36,6 +36,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; +import org.springframework.http.StreamingHttpOutputMessage; import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -286,20 +287,47 @@ public class FormHttpMessageConverter implements HttpMessageConverter parts, HttpOutputMessage outputMessage) throws IOException { - byte[] boundary = generateMultipartBoundary(); + private void writeMultipart(final MultiValueMap parts, HttpOutputMessage outputMessage) throws IOException { + final byte[] boundary = generateMultipartBoundary(); Map parameters = Collections.singletonMap("boundary", new String(boundary, "US-ASCII")); MediaType contentType = new MediaType(MediaType.MULTIPART_FORM_DATA, parameters); - outputMessage.getHeaders().setContentType(contentType); - - writeParts(outputMessage.getBody(), parts, boundary); - writeEnd(outputMessage.getBody(), boundary); + HttpHeaders headers = outputMessage.getHeaders(); + headers.setContentType(contentType); + + if (outputMessage instanceof StreamingHttpOutputMessage) { + StreamingHttpOutputMessage streamingOutputMessage = + (StreamingHttpOutputMessage) outputMessage; + streamingOutputMessage.setBody(new StreamingHttpOutputMessage.Body() { + @Override + public void writeTo(OutputStream outputStream) throws IOException { + writeParts(outputStream, parts, boundary); + writeEnd(outputStream, boundary); + } + }); + } + else { + writeParts(outputMessage.getBody(), parts, boundary); + writeEnd(outputMessage.getBody(), boundary); + } } private void writeParts(OutputStream os, MultiValueMap parts, byte[] boundary) throws IOException { diff --git a/spring-web/src/test/java/org/springframework/web/client/AbstractJettyServerTestCase.java b/spring-web/src/test/java/org/springframework/web/client/AbstractJettyServerTestCase.java index 59c82df4907..b56c43960da 100644 --- a/spring-web/src/test/java/org/springframework/web/client/AbstractJettyServerTestCase.java +++ b/spring-web/src/test/java/org/springframework/web/client/AbstractJettyServerTestCase.java @@ -19,6 +19,7 @@ package org.springframework.web.client; import java.io.IOException; import java.util.Collections; import java.util.List; +import java.util.Map; import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; @@ -85,6 +86,7 @@ public class AbstractJettyServerTestCase { handler.addServlet(new ServletHolder(new ErrorServlet(500)), "/status/server"); handler.addServlet(new ServletHolder(new UriServlet()), "/uri/*"); handler.addServlet(new ServletHolder(new MultipartServlet()), "/multipart"); + handler.addServlet(new ServletHolder(new FormServlet()), "/form"); handler.addServlet(new ServletHolder(new DeleteServlet()), "/delete"); handler.addServlet( new ServletHolder(new PutServlet(helloWorld, bytes, textContentType)), @@ -286,6 +288,28 @@ public class AbstractJettyServerTestCase { } } + @SuppressWarnings("serial") + private static class FormServlet extends HttpServlet { + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + assertEquals(MediaType.APPLICATION_FORM_URLENCODED_VALUE, + req.getContentType()); + + Map parameters = req.getParameterMap(); + assertEquals(2, parameters.size()); + + String[] values = parameters.get("name 1"); + assertEquals(1, values.length); + assertEquals("value 1", values[0]); + + values = parameters.get("name 2"); + assertEquals(2, values.length); + assertEquals("value 2+1", values[0]); + assertEquals("value 2+2", values[1]); + } + } + @SuppressWarnings("serial") private static class DeleteServlet extends HttpServlet { diff --git a/spring-web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java b/spring-web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java index b5be18bf83b..5af86fe6257 100644 --- a/spring-web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java @@ -179,6 +179,16 @@ public class RestTemplateIntegrationTests extends AbstractJettyServerTestCase { template.postForLocation(baseUrl + "/multipart", parts); } + @Test + public void form() throws UnsupportedEncodingException { + MultiValueMap form = new LinkedMultiValueMap(); + form.add("name 1", "value 1"); + form.add("name 2", "value 2+1"); + form.add("name 2", "value 2+2"); + + template.postForLocation(baseUrl + "/form", form); + } + @Test public void exchangeGet() throws Exception { HttpHeaders requestHeaders = new HttpHeaders();