Download Binary File from Okhttp

Download binary file from OKHTTP

Getting ByteStream from OKHTTP

I've been digging around in the Documentation of OkHttp you need to go this way

use this method :

response.body().byteStream() wich will return an InputStream

so you can simply use a BufferedReader or any other alternative

OkHttpClient client = new OkHttpClient();
request = new Request.Builder().url("URL string here")
.addHeader("X-CSRFToken", csrftoken)
.addHeader("Content-Type", "application/json")
.build();
response = getClient().newCall(request).execute();

InputStream in = response.body().byteStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String result, line = reader.readLine();
result = line;
while((line = reader.readLine()) != null) {
result += line;
}
System.out.println(result);
response.body().close();

Binary File Download using OkHTTP Client get corrupted

If your BUFFER_SIZE is not full at the last read then you will have wrong data written in file:

You have

fileOutputStream.write(BUFFER_SIZE);

you should have:

fileOutputStream.write(BUFFER_SIZE, 0, byteRead);

EDIT1: I would also sugest to replace this part of the code:

while (true) {
int byteRead = inputStream.read(BUFFER_SIZE);
if (byteRead == -1) {
break;
}

With a better approach:

int byteRead;
while ( (byteRead = inputStream.read(BUFFER_SIZE)) > 0 ) {

Upload binary file with okhttp from resources

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.

How can I more efficently download large files over http?

As of version 11, Java has a built-in HttpClient which implements

asynchronous streams of data with non-blocking back pressure

and that's what you need if you want your code to run only when there's data to process.

If you can afford to upgrade to Java 11, you'll be able to solve your problem out of the box, using the HttpResponse.BodyHandlers.ofFile body handler. You won't have to implement any data transfer logic on your own.

Kotlin example:

fun main(args: Array<String>) {    
val client = HttpClient.newHttpClient()

val request = HttpRequest.newBuilder()
.uri(URI.create("https://www.google.com"))
.GET()
.build()

println("Starting download...")
client.send(request, HttpResponse.BodyHandlers.ofFile(Paths.get("google.html")))
println("Done with download.")
}

Why okhttp internal package source file name start with -?

It's a convention taken from Okio https://github.com/square/okio/blob/master/okio/src/jvmMain/kotlin/okio/-JvmPlatform.kt

Effectively makes these completely inaccessible to Java code.Sample Image



Related Topics



Leave a reply



Submit