Télécharger le fichier binary depuis OKHTTP

J’utilise le client OKHTTP pour la mise en réseau dans mon application Android.

Cet exemple montre comment télécharger un fichier binary. Je voudrais savoir comment obtenir un stream d’entrée de téléchargement de fichiers binarys avec le client OKHTTP.

Voici la liste de l’exemple:

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

Le code actuel pour obtenir une demande simple est:

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

Maintenant, comment convertir la réponse en InputStream ? Quelque chose de similaire à la réponse du Apache HTTP Client comme ceci pour la réponse OkHttp :

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

MODIFIER

Réponse acceptée ci-dessous. Mon code modifié:

 request = new Request.Builder().url(urlSsortingng).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(); 

Obtenir ByteStream d’OKHTTP

J’ai creusé dans la documentation d’ OkHttp, vous devez aller de cette façon

utilisez cette méthode:

response.body (). byteStream () qui renverra un InputStream

donc vous pouvez simplement utiliser un BufferedReader ou toute autre alternative

 OkHttpClient client = new OkHttpClient(); request = new Request.Builder().url("URL ssortingng 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)); Ssortingng result, line = reader.readLine(); result = line; while((line = reader.readLine()) != null) { result += line; } System.out.println(result); response.body().close(); 

Pour ce que cela vaut, je recommanderais response.body().source() partir de okio (puisque OkHttp le supporte déjà en natif) afin de pouvoir manipuler plus facilement une grande quantité de données pouvant venir lors du téléchargement d’un fichier.

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

Quelques avantages tirés de la documentation par rapport à InputStream:

Cette interface est fonctionnellement équivalente à InputStream. InputStream nécessite plusieurs couches lorsque les données consommées sont hétérogènes: un DataInputStream pour les valeurs primitives, un BufferedInputStream pour la mise en mémoire tampon et InputStreamReader pour les chaînes. Cette classe utilise BufferedSource pour tout ce qui précède. Source évite la méthode impossible à implémenter available (). Au lieu de cela, les appelants spécifient le nombre d’octets requirejs.

La source omet la marque et l’état de réinitialisation dangereux à composer qui sont suivis par InputStream; les appelants au lieu de cela juste tamponner ce dont ils ont besoin.

Lors de l’implémentation d’une source, vous n’avez pas à vous soucier de la méthode de lecture à un octet qui est difficile à implémenter efficacement et qui renvoie l’une des 257 valeurs possibles.

Et la source a une méthode de saut plus forte: BufferedSource.skip (long) ne retournera pas prématurément.

La meilleure option à télécharger (basée sur le code source “okio”)

 private void download(@NonNull Ssortingng 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(); } 

Voici comment j’utilise les bibliothèques Okhttp + Okio tout en publiant la progression du téléchargement après chaque téléchargement de morceau:

 public static final int DOWNLOAD_CHUNK_SIZE = 2048; //Same as Okio Segment.SIZE try { Request request = new Request.Builder().url(uri.toSsortingng()).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); } 

Une meilleure solution est d’utiliser OkHttpClient comme:

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