From 3fd74f63bc66c4fc649e89229e6e91b04bdfa2fc Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 31 Jan 2008 16:56:25 +0000 Subject: [PATCH] MIME multipart/form-data: added method to calculate the content length of a multipart entity. This method buffers only small amount of data in memory in order to determine the total git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@617158 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/client/mime/HttpMultipart.java | 65 +++++++++++++++++-- .../http/client/mime/TestMultipartForm.java | 25 ++++--- 2 files changed, 74 insertions(+), 16 deletions(-) diff --git a/module-httpmime/src/main/java/org/apache/http/client/mime/HttpMultipart.java b/module-httpmime/src/main/java/org/apache/http/client/mime/HttpMultipart.java index e71765f3d..61ef5ed19 100644 --- a/module-httpmime/src/main/java/org/apache/http/client/mime/HttpMultipart.java +++ b/module-httpmime/src/main/java/org/apache/http/client/mime/HttpMultipart.java @@ -38,9 +38,12 @@ import java.io.OutputStreamWriter; import java.nio.charset.Charset; import java.util.List; +import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.http.client.mime.content.ContentBody; import org.apache.http.protocol.HTTP; import org.apache.james.mime4j.field.ContentTypeField; import org.apache.james.mime4j.field.Field; +import org.apache.james.mime4j.message.Body; import org.apache.james.mime4j.message.BodyPart; import org.apache.james.mime4j.message.Entity; import org.apache.james.mime4j.message.Multipart; @@ -68,13 +71,10 @@ public class HttpMultipart extends Multipart { this.mode = mode; } - @Override - public void writeTo(OutputStream out) throws IOException { + protected Charset getCharset() { Entity e = getParent(); - ContentTypeField cField = (ContentTypeField) e.getHeader().getField( Field.CONTENT_TYPE); - String boundary = cField.getBoundary(); Charset charset = null; switch (this.mode) { @@ -89,8 +89,21 @@ public class HttpMultipart extends Multipart { } break; } + return charset; + } + + protected String getBoundary() { + Entity e = getParent(); + ContentTypeField cField = (ContentTypeField) e.getHeader().getField( + Field.CONTENT_TYPE); + return cField.getBoundary(); + } + + private void writeTo(final OutputStream out, boolean writeContent) throws IOException { List bodyParts = getBodyParts(); + Charset charset = getCharset(); + String boundary = getBoundary(); BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(out, charset), @@ -107,7 +120,10 @@ public class HttpMultipart extends Multipart { writer.write("\r\n"); writer.flush(); BodyPart part = (BodyPart) bodyParts.get(i); - part.writeTo(out); + part.getHeader().writeTo(out); + if (writeContent) { + part.getBody().writeTo(out); + } writer.write("\r\n"); } @@ -138,7 +154,9 @@ public class HttpMultipart extends Multipart { writer.write("\r\n"); writer.write("\r\n"); writer.flush(); - part.getBody().writeTo(out); + if (writeContent) { + part.getBody().writeTo(out); + } writer.write("\r\n"); } @@ -151,5 +169,40 @@ public class HttpMultipart extends Multipart { break; } } + + @Override + public void writeTo(final OutputStream out) throws IOException { + writeTo(out, true); + } + + public long getTotalLength() { + List bodyParts = getBodyParts(); + + long contentLen = 0; + for (int i = 0; i < bodyParts.size(); i++) { + BodyPart part = (BodyPart) bodyParts.get(i); + Body body = part.getBody(); + if (body instanceof ContentBody) { + long len = ((ContentBody) body).getContentLength(); + if (len >= 0) { + contentLen += len; + } else { + return -1; + } + } else { + return -1; + } + } + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + writeTo(out, false); + byte[] extra = out.toByteArray(); + return contentLen + extra.length; + } catch (IOException ex) { + // Should never happen + return -1; + } + } } diff --git a/module-httpmime/src/test/java/org/apache/http/client/mime/TestMultipartForm.java b/module-httpmime/src/test/java/org/apache/http/client/mime/TestMultipartForm.java index e1c15307d..281dc77ed 100644 --- a/module-httpmime/src/test/java/org/apache/http/client/mime/TestMultipartForm.java +++ b/module-httpmime/src/test/java/org/apache/http/client/mime/TestMultipartForm.java @@ -50,7 +50,6 @@ import org.apache.james.mime4j.field.Field; import org.apache.james.mime4j.message.BodyPart; import org.apache.james.mime4j.message.Header; import org.apache.james.mime4j.message.Message; -import org.apache.james.mime4j.message.Multipart; public class TestMultipartForm extends TestCase { @@ -78,7 +77,7 @@ public class TestMultipartForm extends TestCase { Field.parse("Content-Type: multipart/form-data; boundary=foo")); message.setHeader(header); - Multipart multipart = new HttpMultipart(); + HttpMultipart multipart = new HttpMultipart(); multipart.setParent(message); BodyPart p1 = new BodyPart(); Header h1 = new Header(); @@ -121,6 +120,7 @@ public class TestMultipartForm extends TestCase { "\r\n"; String s = out.toString("US-ASCII"); assertEquals(expected, s); + assertEquals(s.length(), multipart.getTotalLength()); } public void testMultipartFormStringParts() throws Exception { @@ -130,7 +130,7 @@ public class TestMultipartForm extends TestCase { Field.parse("Content-Type: multipart/form-data; boundary=foo")); message.setHeader(header); - Multipart multipart = new HttpMultipart(); + HttpMultipart multipart = new HttpMultipart(); multipart.setParent(message); FormBodyPart p1 = new FormBodyPart( "field1", @@ -173,6 +173,7 @@ public class TestMultipartForm extends TestCase { "\r\n"; String s = out.toString("US-ASCII"); assertEquals(expected, s); + assertEquals(s.length(), multipart.getTotalLength()); } public void testMultipartFormBinaryParts() throws Exception { @@ -191,7 +192,7 @@ public class TestMultipartForm extends TestCase { writer.close(); } - Multipart multipart = new HttpMultipart(); + HttpMultipart multipart = new HttpMultipart(); multipart.setParent(message); FormBodyPart p1 = new FormBodyPart( "field1", @@ -226,6 +227,7 @@ public class TestMultipartForm extends TestCase { "\r\n"; String s = out.toString("US-ASCII"); assertEquals(expected, s); + assertEquals(-1, multipart.getTotalLength()); tmpfile.delete(); } @@ -279,6 +281,7 @@ public class TestMultipartForm extends TestCase { "\r\n"; String s = out.toString("US-ASCII"); assertEquals(expected, s); + assertEquals(-1, multipart.getTotalLength()); tmpfile.delete(); } @@ -354,6 +357,7 @@ public class TestMultipartForm extends TestCase { "\r\n"; String s = out.toString("UTF-8"); assertEquals(expected, s); + assertEquals(-1, multipart.getTotalLength()); tmpfile.delete(); } @@ -368,7 +372,7 @@ public class TestMultipartForm extends TestCase { Field.parse("Content-Type: multipart/form-data; boundary=foo")); message.setHeader(header); - Multipart multipart = new HttpMultipart(); + HttpMultipart multipart = new HttpMultipart(); multipart.setParent(message); FormBodyPart p1 = new FormBodyPart( "field1", @@ -387,11 +391,11 @@ public class TestMultipartForm extends TestCase { ByteArrayOutputStream out2 = new ByteArrayOutputStream(); out2.write(("\r\n" + - "--foo\r\n" + - "Content-Disposition: form-data; name=\"field1\"\r\n" + - "Content-Type: text/plain; charset=ISO-8859-1\r\n" + - "Content-Transfer-Encoding: 8bit\r\n" + - "\r\n").getBytes("US-ASCII")); + "--foo\r\n" + + "Content-Disposition: form-data; name=\"field1\"\r\n" + + "Content-Type: text/plain; charset=ISO-8859-1\r\n" + + "Content-Transfer-Encoding: 8bit\r\n" + + "\r\n").getBytes("US-ASCII")); out2.write(s1.getBytes("ISO-8859-1")); out2.write(("\r\n" + "--foo\r\n" + @@ -412,6 +416,7 @@ public class TestMultipartForm extends TestCase { for (int i = 0; i < actual.length; i++) { assertEquals(expected[i], actual[i]); } + assertEquals(expected.length, multipart.getTotalLength()); } }