Ich verwende den OKHTTP-Client für das Netzwerk in meiner Android-Anwendung.
Dieses Beispiel zeigt, wie eine Binärdatei hochgeladen wird. Ich würde gerne wissen, wie man einen Inputstream für das Herunterladen von Binärdateien mit dem OKHTTP-Client erhält.
Hier ist die Auflistung des Beispiels:
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);
}
}
}
Der aktuelle Code für eine einfache Abrufanforderung lautet:
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();
Wie konvertiere ich nun die Antwort in InputStream
. Etwas Ähnliches wie eine Antwort von Apache HTTP Client
dieser für die OkHttp
Antwort:
InputStream is = response.getEntity().getContent();
BEARBEITEN
Akzeptierte Antwort von unten. Mein geänderter Code:
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();
content://
Inputstream darauf gestoßen)Antworten:
ByteStream von OKHTTP abrufen
Ich habe in der Dokumentation von OkHttp herumgegraben , dass Sie diesen Weg gehen müssen
Verwenden Sie diese Methode:
Sie können also einfach einen BufferedReader oder eine andere Alternative verwenden
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();
quelle
BufferedReader
mit Binärdaten verwenden. Es wird durch die unnötige Decodierung von Byte zu Zeichen beschädigt.Für das, was es wert ist, würde ich
response.body().source()
von okio empfehlen (da OkHttp es bereits nativ unterstützt), um eine einfachere Möglichkeit zu haben, eine große Datenmenge zu bearbeiten, die beim Herunterladen einer Datei auftreten kann.@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(); }
Einige Vorteile aus der Dokumentation im Vergleich zu InputStream:
quelle
while ((source.read(fileSink.buffer(), 2048)) != -1)
Die beste Option zum Herunterladen (basierend auf dem Quellcode "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(); }
quelle
flush()
undclose()
in einenfinally
Block einfügen, um sicherzustellen, dass Ausnahmen weiterhin gelöscht und geschlossen werden.So verwende ich Okhttp + Okio- Bibliotheken, während ich den Download-Fortschritt nach jedem Chunk-Download veröffentliche:
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); }
quelle
getDownloadPathFrom
tunwhile (read = (source.read(sink.buffer(), DOWNLOAD_CHUNK_SIZE)) != -1) {
sollte seinwhile ((read = source.read(sink.buffer(), DOWNLOAD_CHUNK_SIZE)) != -1) {
sink.emit();
denwhile
Zyklus nicht aufrufen, verbrauchen Sie viel Speicher.Bessere Lösung ist die Verwendung von OkHttpClient als:
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); } });
quelle
Kotlin-Version basierend auf Kiddouk-Antwort
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()
quelle