question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Feature Request] - RequestBody supports InputStream

See original GitHub issue

I would like to submit a PR to add support for InputStreams in the RequestBody class. As of now, RequestBody supports the following:

  • create(MediaType contentType, String content)
  • create(MediaType contentType, ByteString content)
  • create(MediaType contentType, byte[] content)
  • create(MediaType contentType, byte[] content, final int offset, final int byteCount)
  • create(MediaType contentType, File file)

I would like to go one step further and add support for InputStream:

  • create(MediaType contentType, Inputream inputStream)

Similar to https://stackoverflow.com/a/25384793:

  public static RequestBody create(final @Nullable MediaType contentType, final InputStream inputStream) {
    if (inputStream == null) throw new NullPointerException("inputStream == null");

    return new RequestBody() {
      @Override public @Nullable MediaType contentType() {
        return contentType;
      }

      @Override public long contentLength() {
        return inputStream.available() == 0 ? -1 : inputStream.available();
      }

      @Override public void writeTo(BufferedSink sink) throws IOException {
        Source source = null;
        try {
          source = Okio.source(inputStream);
          sink.writeAll(source);
        } finally {
          Util.closeQuietly(source);
        }
      }
    };
  }

This would be nice to have since Okio.source support both File and InputStream.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:2
  • Comments:13 (9 by maintainers)

github_iconTop GitHub Comments

50reactions
jaredsburrowscommented, Sep 5, 2017

@JakeWharton I know it is not an Android library. I figured after the first comment, I would have to keep this code locally and not be able to make a PR. Something like this:

public class InputStreamRequestBody extends RequestBody {
    private final InputStream inputStream;
    private final MediaType contentType;

    public InputStreamRequestBody(MediaType contentType, InputStream inputStream) {
        if (inputStream == null) throw new NullPointerException("inputStream == null");
        this.contentType = contentType;
        this.inputStream = inputStream;
    }

    @Nullable
    @Override
    public MediaType contentType() {
        return contentType;
    }

    @Override
    public long contentLength() throws IOException {
        return inputStream.available() == 0 ? -1 : inputStream.available();
    }

    @Override
    public void writeTo(@NonNull BufferedSink sink) throws IOException {
        Source source = null;
        try {
            source = Okio.source(inputStream);
            sink.writeAll(source);
        } finally {
            Util.closeQuietly(source);
        }
    }
}

Based on your changes, @JakeWharton, to be changed to handle Uri:

public class InputStreamRequestBody extends RequestBody {
    private final MediaType contentType;
    private final ContentResolver contentResolver;
    private final Uri uri;

    public InputStreamRequestBody(MediaType contentType, ContentResolver contentResolver, Uri uri) {
        if (uri == null) throw new NullPointerException("uri == null");
        this.contentType = contentType;
        this.contentResolver = contentResolver;
        this.uri = uri;
    }

    @Nullable
    @Override
    public MediaType contentType() {
        return contentType;
    }

    @Override
    public long contentLength() throws IOException {
        return -1;
    }

    @Override
    public void writeTo(@NonNull BufferedSink sink) throws IOException {
        sink.writeAll(Okio.source(contentResolver.openInputStream(uri)));
    }
}
9reactions
Miha-x64commented, Jun 10, 2020

@neiljaywarner

val upload = POST("/updatePhoto",
    Field("id", uuid),
    Part("photo", Stream("image/*"), { "photo.jpg" }),
    Response<Boolean>())

val doUpload = okHttpClient.template(baseUrl, upload,
    blocking { body?.close(); isSuccessful })

doUpload(id) { contentResolver.openInputStream(uri) }

https://github.com/Miha-x64/Lychee#http

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why RequestBody in HttpServletRequest is an InputStream?
Using an InputStream gives freedom to the servlet implementation to source the request body value from wherever it likes.
Read more >
RequestBody (AWS SDK for Java - 2.18.38) - Amazon AWS
Represents the body of an HTTP request. Must be provided for operations that have a streaming input. Offers various convenience factory methods from...
Read more >
How can one access raw content of the request stream?
I would very much like to have access to the underlying raw inputstream. I have found a couple posts that ... Sending the...
Read more >
File Upload - Swagger
Swagger 2.0 supports file upload requests with Content-Type: multipart/form-data , but does not care about the HTTP method. You can use POST, PUT...
Read more >
Web on Servlet Stack - Spring
All HandlerMapping implementations support handler interceptors that are useful when you want to apply specific functionality to certain requests — for example, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found