Descargar archivo binario de OKHTTP

Estoy usando el cliente OKHTTP para redes en mi aplicación de Android.

Este ejemplo muestra cómo cargar archivos binarios. Me gustaría saber cómo obtener el flujo de entrada de la descarga de archivos binarios con el cliente OKHTTP.

Aquí está la lista del ejemplo:

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); } } } 

El código actual para la solicitud de obtención simple es:

 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(); 

Ahora, ¿cómo convierto la respuesta a InputStream ? Algo similar a la respuesta de Apache HTTP Client como este para la respuesta OkHttp :

 InputStream is = response.getEntity().getContent(); 

EDITAR

Respuesta aceptada de abajo. Mi código modificado:

 request = new Request.Builder().url(urlString).build(); response = getClient().newCall(request).execute(); InputStream is = response.body().byteStream(); BufferedInputStream input = new BufferedInputStream(is); OutputStream output = new FileOutputStream(file); byte[] data = new byte[1024]; long total = 0; while ((count = input.read(data)) != -1) { total += count; output.write(data, 0, count); } output.flush(); output.close(); input.close(); 

Obtener ByteStream de OKHTTP

He estado hurgando en la Documentación de OkHttp, tienes que ir de esta manera

usa este método:

response.body (). byteStream () que devolverá un InputStream

así que puedes simplemente usar un BufferedReader o cualquier otra alternativa

 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(); 

Por lo que vale, recomendaría response.body().source() de okio (ya que OkHttp ya lo está soportando de forma nativa) para disfrutar de una manera más fácil de manipular una gran cantidad de datos que pueden surgir al descargar un archivo.

 @Override public void onResponse(Call call, Response response) throws IOException { File downloadedFile = new File(context.getCacheDir(), filename); BufferedSink sink = Okio.buffer(Okio.sink(downloadedFile)); sink.writeAll(response.body().source()); sink.close(); } 

Un par de ventajas tomadas de la documentación en comparación con InputStream:

Esta interfaz es funcionalmente equivalente a InputStream. InputStream requiere varias capas cuando los datos consumidos son heterogéneos: un DataInputStream para valores primitivos, un BufferedInputStream para almacenamiento en búfer y InputStreamReader para cadenas. Esta clase usa BufferedSource para todo lo anterior. Source evita el método impossible (disponible) para implementar (). En cambio, las personas que llaman especifican cuántos bytes requieren.

Source omite el estado de marca insegura para componer y restablecer que InputStream rastrea; las personas que llaman en cambio solo almacenan lo que necesitan.

Al implementar una fuente, no necesita preocuparse por el método de lectura de byte único que es incómodo de implementar de manera eficiente y que devuelve uno de los 257 valores posibles.

Y la fuente tiene un método de omisión más fuerte: BufferedSource.skip (long) no regresará prematuramente.

La mejor opción para descargar (según el código fuente “okio”)

 private void download(@NonNull String url, @NonNull File destFile) throws IOException { Request request = new Request.Builder().url(url).build(); Response response = okHttpClient.newCall(request).execute(); ResponseBody body = response.body(); long contentLength = body.contentLength(); BufferedSource source = body.source(); BufferedSink sink = Okio.buffer(Okio.sink(destFile)); Buffer sinkBuffer = sink.buffer(); long totalBytesRead = 0; int bufferSize = 8 * 1024; for (long bytesRead; (bytesRead = source.read(sinkBuffer, bufferSize)) != -1; ) { sink.emit(); totalBytesRead += bytesRead; int progress = (int) ((totalBytesRead * 100) / contentLength); publishProgress(progress); } sink.flush(); sink.close(); source.close(); } 

Así es como utilizo las bibliotecas Okhttp + Okio mientras publico el progreso de descarga después de cada descarga de fragmento:

 public static final int DOWNLOAD_CHUNK_SIZE = 2048; //Same as Okio Segment.SIZE try { Request request = new Request.Builder().url(uri.toString()).build(); Response response = client.newCall(request).execute(); ResponseBody body = response.body(); long contentLength = body.contentLength(); BufferedSource source = body.source(); File file = new File(getDownloadPathFrom(uri)); BufferedSink sink = Okio.buffer(Okio.sink(file)); long totalRead = 0; long read = 0; while (read = (source.read(sink.buffer(), DOWNLOAD_CHUNK_SIZE)) != -1) { totalRead += read; int progress = (int) ((totalRead * 100) / contentLength); publishProgress(progress); } sink.writeAll(source); sink.flush(); sink.close(); publishProgress(FileInfo.FULL); } catch (IOException e) { publishProgress(FileInfo.CODE_DOWNLOAD_ERROR); Logger.reportException(e); } 

La mejor solución es usar OkHttpClient como:

 OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt") .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); // Headers responseHeaders = response.headers(); // for (int i = 0; i < responseHeaders.size(); i++) { // System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i)); // } // System.out.println(response.body().string()); 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); } });