Download binary file from OKHTTP

前端 未结 6 1787
不知归路
不知归路 2020-11-22 11:53

I am using OKHTTP client for networking in my android application.

This example shows how to upload binary file. I would like to know how to get inputstream of binary

相关标签:
6条回答
  • 2020-11-22 12:32

    This is how I use Okhttp + Okio libraries while publishing download progress after every chunk download:

    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);
    }
    
    0 讨论(0)
  • 2020-11-22 12:33

    Kotlin version based on kiddouk answer

     val request = Request.Builder().url(url).build()
     val response = OkHttpClient().newCall(request).execute()
     val downloadedFile = File(cacheDir, filename)
     val sink: BufferedSink = downloadedFile.sink().buffer()
     sink.writeAll(response.body!!.source())
     sink.close()
    
    0 讨论(0)
  • 2020-11-22 12:45

    Better solution is to use OkHttpClient as:

    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);
    
    
                    }
                });
    
    0 讨论(0)
  • 2020-11-22 12:46

    The best option to download (based on source code "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();
    }
    
    0 讨论(0)
  • 2020-11-22 12:49

    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();
    
    0 讨论(0)
  • 2020-11-22 12:50

    For what it's worth, I would recommend response.body().source() from okio (since OkHttp is already supporting it natively) in order to enjoy an easier way to manipulate a large quantity of data that can come when downloading a file.

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

    A couple of advantages taken from the documentation in comparison with InputStream:

    This interface is functionally equivalent to InputStream. InputStream requires multiple layers when consumed data is heterogeneous: a DataInputStream for primitive values, a BufferedInputStream for buffering, and InputStreamReader for strings. This class uses BufferedSource for all of the above. Source avoids the impossible-to-implement available() method. Instead callers specify how many bytes they require.

    Source omits the unsafe-to-compose mark and reset state that's tracked by InputStream; callers instead just buffer what they need.

    When implementing a source, you need not worry about the single-byte read method that is awkward to implement efficiently and that returns one of 257 possible values.

    And source has a stronger skip method: BufferedSource.skip(long) won't return prematurely.

    0 讨论(0)
提交回复
热议问题