web-dev-qa-db-fra.com

Téléchargez le fichier binaire à partir de OKHTTP

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

Cet exemple montre comment télécharger un fichier binaire. Je voudrais savoir comment obtenir le flux d'entrée du téléchargement de fichiers binaires 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 une requête get simple est:

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

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

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

MODIFIER

Réponse acceptée d'en bas. Mon code modifié:

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

Obtention de ByteStream à partir de OKHTTP

J'ai fouillé dans la documentation de OkHttp vous devez suivre cette voie

utilisez cette méthode:

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

afin que vous puissiez simplement utiliser un BufferedReader ou toute autre 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();
30
Nadir Belhaj

Pour ce que cela vaut, je recommanderais response.body().source() de okio (puisque OkHttp le supporte déjà en mode natif) afin de profiter d'un moyen plus simple de manipuler 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 utilisées sont hétérogènes: un DataInputStream pour les valeurs primitives, un BufferedInputStream pour la mise en mémoire tampon et InputStreamReader pour des chaînes. Cette classe utilise BufferedSource pour tout ce qui précède. Source évite la méthode impossible à mettre en œuvre available (). Au lieu de cela, les appelants spécifient le nombre d'octets dont ils ont besoin.

La source omet la marque non sûre à composer et l’état de réinitialisation suivi par InputStream; les appelants se contentent de mettre en mémoire tampon 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 sur un octet qu'il est difficile d'implémenter efficacement et qui renvoie l'une des 257 valeurs possibles.

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

160
kiddouk

Voici comment j'utilise les bibliothèques Okhttp + Okio lors de la publication de la progression du téléchargement après chaque téléchargement de bloc:

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);
}
9
Shubham Chaudhary

La meilleure option à télécharger (basée sur le code source "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();
}
9
e.shishkin

Une meilleure solution consiste à utiliser OkHttpClient en tant que:

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


                }
            });
5
Joolah