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.
A RequestBody occasionally needs to be written multiple times, which this
would not allow. The current overloads all create instances which support
this, and I think we intentionally want to make it hard to create one that
does not support this.
On Tue, Sep 5, 2017 at 5:21 PM Jared Burrows notifications@github.com
wrote:
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 File file) {
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.—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/square/okhttp/issues/3585, or mute the thread
https://github.com/notifications/unsubscribe-auth/AAEEEZFuHECAXOV5XnYySXzNGKCQ6uqTks5sfbtKgaJpZM4PNii9
.
Are RequestBodys written multiple times on retries?
What would you suggest for contentResolver.openInputStream(uri)? Save it to a file first then use create(MediaType contentType, File file)? Even that uses Okio.source when uses a FileInputStream.
Inside of writeTo call that method and then call
sink.writeAll(Okio.source(steam)).
On Tue, Sep 5, 2017 at 5:46 PM Jared Burrows notifications@github.com
wrote:
Are RequestBodys written multiple times on retries?
What would you suggest for contentResolver.openInputStream(uri)? Save it
to a file first then use create(MediaType contentType, File file)? Even
that uses Okio.source when uses a FileInputStream.—
You are receiving this because you commented.Reply to this email directly, view it on GitHub
https://github.com/square/okhttp/issues/3585#issuecomment-327313068, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAEEEeFVXL3lWZyw8tf-Kd5UIza8_1eJks5sfcFMgaJpZM4PNii9
.
Also, request bodies may be written zero times, in which case this would leak the input stream.
@swankjesse Maybe I could pass a Uri instead of InputStream in the class to prevent leaking using.
@JakeWharton If I call contentResolver.openInputStream(uri) inside of writeTo, how do I update the long contentLength() before the request is made?
OkHttp isn't an Android library and can't reference Uri. Use -1 for length.
On Tue, Sep 5, 2017 at 6:06 PM Jared Burrows notifications@github.com
wrote:
@swankjesse https://github.com/swankjesse Maybe I could pass a Uri
instead of InputStream in the class to prevent leaking using.@JakeWharton https://github.com/jakewharton If I call
contentResolver.openInputStream(uri) inside of writeTo, how do I update
the long contentLength() before the request is made?—
You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub
https://github.com/square/okhttp/issues/3585#issuecomment-327317191, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAEEEU77khg3MDG3YOeq1wf8bFp61jVvks5sfcXGgaJpZM4PNii9
.
@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)));
}
}
Ah, yes. Definitely do that to make it reusable in your own code. Don't
forget try-with-resources:
try (Source source = Okio.source(contentResolver.openInputStream(uri))) {
sink.writeAll(source);
}
On Tue, Sep 5, 2017 at 6:16 PM Jared Burrows notifications@github.com
wrote:
@JakeWharton https://github.com/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 https://github.com/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))); }}
—
You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub
https://github.com/square/okhttp/issues/3585#issuecomment-327319196, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAEEEaaL1po9CilQcaTrQuBEKNofh3mzks5sfcgqgaJpZM4PNii9
.
@JakeWharton Based on your first comment, I guess I will close this because using TypeInputStream directly does not work very well with the current implementation of RequestBody.
@JakeWharton @jaredsburrows 3 years later. what's the best way to go from a android uri to okhttp "put"?
@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) }
Most helpful comment
@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:
Based on your changes, @JakeWharton, to be changed to handle
Uri: