Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upload binary file with okhttp from resources

Tags:

android

okhttp

I need to upload a binary file bundled in an apk to a server using okhttp. Using urlconnection, you can simply get an inputstream to an asset and then put that into your request. However, okhttp only gives you the option of uploading byte arrays, strings, or files. Since you can't get a file path for an asset bundled in the apk, is the only option to copy the file to the local file directory (I'd rather not do that) and then give the file to okhttp? Is there no way to simply make a request using the assetinputstream directly to the web server?

EDIT: I used the accepted answer but instead of making a static utility class I simply subclassed RequestBody

 public class InputStreamRequestBody extends RequestBody {

private InputStream inputStream;
private MediaType mediaType;

public static RequestBody create(final MediaType mediaType, final InputStream inputStream) {


    return new InputStreamRequestBody(inputStream, mediaType);
}

private InputStreamRequestBody(InputStream inputStream, MediaType mediaType) {
    this.inputStream = inputStream;
    this.mediaType = mediaType;
}

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

@Override
public long contentLength() {
    try {
        return inputStream.available();
    } catch (IOException e) {
        return 0;
    }
}

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

My only concern with this approach is the unreliability of inputstream.available() for content-length. The static constructor is to match okhttp's internal implementation

like image 294
dabluck Avatar asked Aug 18 '14 16:08

dabluck


People also ask

How to download file using OkHttp?

Requesting a Binary File The process of downloading the file has four steps. Create the request using the URL. Execute the request and receive a response. Get the body of the response, or fail if it's null.

Where is OkHttp used?

As of Android 5.0, OkHttp is part of the Android platform and is used for all HTTP calls.

What is OkHttp in Java?

OkHttp is an efficient HTTP & HTTP/2 client for Android and Java applications. It comes with advanced features, such as connection pooling (if HTTP/2 isn't available), transparent GZIP compression, and response caching, to avoid the network completely for repeated requests.

What is the underlying library of OkHttp?

Beginning with Mobile SDK 4.2, the Android REST request system uses OkHttp (v3. 2.0), an open-source external library from Square Open Source, as its underlying architecture. This library replaces the Google Volley library from past releases.


1 Answers

You might not be able to do it directly using the library but you could create a little utility class which would do it for you. You could then simply re-use it everywhere you need it.

public class RequestBodyUtil {

    public static RequestBody create(final MediaType mediaType, final InputStream inputStream) {
        return new RequestBody() {
            @Override
            public MediaType contentType() {
                return mediaType;
            }

            @Override
            public long contentLength() {
                try {
                    return inputStream.available();
                } catch (IOException e) {
                    return 0;
                }
            }

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

Then simply use it like so

OkHttpClient client = new OkHttpClient();

MediaType MEDIA_TYPE_MARKDOWN
        = MediaType.parse("text/x-markdown; charset=utf-8");

InputStream inputStream = getAssets().open("README.md");

RequestBody requestBody = RequestBodyUtil.create(MEDIA_TYPE_MARKDOWN, inputStream);
Request request = new Request.Builder()
        .url("https://api.github.com/markdown/raw")
        .post(requestBody)
        .build();

Response response = client.newCall(request).execute();
if (!response.isSuccessful())
    throw new IOException("Unexpected code " + response);

Log.d("POST", response.body().string());    

This example code was based on this code. Replace the Assets file name and the MediaType with your own.

like image 60
Miguel Avatar answered Oct 27 '22 06:10

Miguel