-
Notifications
You must be signed in to change notification settings - Fork 9.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature Request] - RequestBody supports InputStream #3585
Comments
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 ***@***.***> 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
<#3585>, or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAEEEZFuHECAXOV5XnYySXzNGKCQ6uqTks5sfbtKgaJpZM4PNii9>
.
|
Are What would you suggest for |
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 ***@***.***> 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
<#3585 (comment)>, 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 @JakeWharton If I call |
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 ***@***.***> 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
<#3585 (comment)>, 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:
Based on your changes, @JakeWharton, to be changed to handle
|
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 ***@***.***> 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 ***@***.*** 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 ***@***.*** 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
<#3585 (comment)>, 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 |
We can't use InputStream directly because of square/okhttp#3585. Instead of being specific and pass a ContentResolver and Uri, the new method takes an InputStreamProvider, which is an interface providing an InputStream. This way, it can be called several times if needed by OkHttp.
@JakeWharton @jaredsburrows 3 years later. what's the best way to go from a android uri to okhttp "put"? |
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) } |
My take on this. |
@jemshit Thanks, we can possibly make this some samples for documentation inside the project. @swankjesse had the most conniving argument for why we don't support this inbuilt
|
I would like to submit a PR to add support for
InputStream
s in theRequestBody
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:
This would be nice to have since
Okio.source
support bothFile
andInputStream
.The text was updated successfully, but these errors were encountered: