diff --git a/okhttp-tests/src/test/java/okhttp3/RequestTest.java b/okhttp-tests/src/test/java/okhttp3/RequestTest.java index 5c205d703149..844a17dd0218 100644 --- a/okhttp-tests/src/test/java/okhttp3/RequestTest.java +++ b/okhttp-tests/src/test/java/okhttp3/RequestTest.java @@ -15,7 +15,10 @@ */ package okhttp3; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; import java.io.File; +import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.net.URI; @@ -30,6 +33,9 @@ import static org.junit.Assert.fail; public final class RequestTest { + + private static final MediaType CONTENTTYPE_TEXT_PLAIN = MediaType.parse("text/plain"); + @Test public void string() throws Exception { MediaType contentType = MediaType.parse("text/plain; charset=utf-8"); RequestBody body = RequestBody.create(contentType, "abc".getBytes(Util.UTF_8)); @@ -87,6 +93,38 @@ public final class RequestTest { assertEquals("Retransmit body", "616263", bodyToHex(body)); } + @Test public void inputStreamFromFile() throws Exception { + File file = createFile("abc"); + try (BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file))) { + RequestBody body = RequestBody.create(CONTENTTYPE_TEXT_PLAIN, inputStream); + checkRequestBodyFeatures(body, CONTENTTYPE_TEXT_PLAIN, 3, "616263"); + } + } + + @Test public void inputStreamFromByteArray() throws Exception { + byte[] bytes = "abc".getBytes(Util.UTF_8); + try (BufferedInputStream inputStream = new BufferedInputStream(new ByteArrayInputStream(bytes))) { + RequestBody body = RequestBody.create(CONTENTTYPE_TEXT_PLAIN, inputStream); + checkRequestBodyFeatures(body, CONTENTTYPE_TEXT_PLAIN, bytes.length, "616263"); + } + } + + private File createFile(String content) throws IOException { + File file = File.createTempFile("RequestTest", "tmp"); + FileWriter writer = new FileWriter(file); + writer.write(content); + writer.close(); + + return file; + } + + private void checkRequestBodyFeatures(RequestBody requestBody, MediaType expectedContentType, int expectedLength, String expectedBody) throws IOException { + assertEquals(expectedContentType, requestBody.contentType()); + assertEquals(expectedLength, requestBody.contentLength()); + assertEquals(expectedBody, bodyToHex(requestBody)); + assertEquals("Retransmit body", expectedBody, bodyToHex(requestBody)); + } + /** Common verbs used for apis such as GitHub, AWS, and Google Cloud. */ @Test public void crudVerbs() throws IOException { MediaType contentType = MediaType.parse("application/json"); diff --git a/okhttp/src/main/java/okhttp3/RequestBody.java b/okhttp/src/main/java/okhttp3/RequestBody.java index 3cb29477d3ae..129549375b74 100644 --- a/okhttp/src/main/java/okhttp3/RequestBody.java +++ b/okhttp/src/main/java/okhttp3/RequestBody.java @@ -15,6 +15,7 @@ */ package okhttp3; +import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; @@ -124,4 +125,38 @@ public static RequestBody create(final @Nullable MediaType contentType, final Fi } }; } + + /** + * Returns a new request body that transmits the content of an {@code inputStream}. + * Note that {@code RequestBody} is not responsible for closing the {@code inputStream}. + */ + public static RequestBody create(final MediaType contentType, + final BufferedInputStream inputStream) { + if (inputStream == null) throw new NullPointerException("inputStream == null"); + + return new RequestBody() { + @Override public MediaType contentType() { + return contentType; + } + + @Override public long contentLength() { + try { + return inputStream.available(); + } catch (IOException e) { + //a IOException is sent if the input stream has been closed, i.e. no content to read. + return 0; + } + } + + @Override public void writeTo(BufferedSink sink) throws IOException { + try { + inputStream.mark(0); + Source source = Okio.source(inputStream); + sink.writeAll(source); + } finally { + inputStream.reset(); + } + } + }; + } }