从OKHTTP下载二进制文件

我在我的android应用程序中使用OKHTTP客户端联网。

这个例子展示了如何上传二进制文件。 我想知道如何用OKHTTP客户端获取二进制文件下载的inputstream。

这里是这个例子的列表:

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

当前的简单获取请求代码是:

 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 。 类似于Apache HTTP Client响应,类似于OkHttp响应:

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

编辑

从下面接受的答案。 我修改的代码:

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

从OKHTTP获取ByteStream

我一直在OkHttp的文档中挖掘,你需要这样做

使用这种方法:

response.body()。byteStream()将返回一个InputStream

所以你可以简单地使用BufferedReader或者其他的select

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

对于它的价值,我会推荐okio的 response.body().source() (因为OkHttp已经在本地支持它),以便享受更简单的方式来处理下载文件时可能出现的大量数据。

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

与InputStream相比,从文档中取得了一些优势:

该接口在function上等同于InputStream。 当消耗的数据是异构的时,InputStream需要多个层:原始值的DataInputStream,缓冲的BufferedInputStream和string的InputStreamReader。 这个类为所有上面使用BufferedSource。 源代码避免了不可能实现的available()方法。 而调用者指定他们需要多less字节。

Source省略InputStream跟踪的不安全标记和复位状态; 呼叫者只需缓冲他们所需要的东西。

在实现源代码时,您不必担心单字节读取方法的高效实现,而且返回257个可能值之一。

源代码有一个更强的跳过方法:BufferedSource.skip(long)不会过早返回。

更好的解决scheme是使用OkHttpClient作为:

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

这是我如何使用Okhttp + Okio库,而每个块下载后发布下载进度:

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

最好的select下载(基于源代码“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(); } 
Interesting Posts