diff --git a/libraries-http-2/src/main/java/com/baeldung/okhttp/download/BinaryFileDownloader.java b/libraries-http-2/src/main/java/com/baeldung/okhttp/download/BinaryFileDownloader.java index e9fb42185b..a2e02c3be8 100644 --- a/libraries-http-2/src/main/java/com/baeldung/okhttp/download/BinaryFileDownloader.java +++ b/libraries-http-2/src/main/java/com/baeldung/okhttp/download/BinaryFileDownloader.java @@ -7,6 +7,9 @@ import okhttp3.ResponseBody; import org.jetbrains.annotations.NotNull; import java.io.IOException; +import java.util.Objects; + +import static org.springframework.http.HttpHeaders.CONTENT_LENGTH; public class BinaryFileDownloader implements AutoCloseable { @@ -22,7 +25,8 @@ public class BinaryFileDownloader implements AutoCloseable { Request request = createRequest(url); Response response = executeRequest(request); ResponseBody responseBody = getResponseBodyOrFail(response); - return write(responseBody); + double length = getResponseLength(response); + return write(responseBody, length); } @NotNull @@ -43,8 +47,12 @@ public class BinaryFileDownloader implements AutoCloseable { return responseBody; } - private long write(ResponseBody responseBody) throws IOException { - return writer.write(responseBody.byteStream()); + private double getResponseLength(Response response) { + return Double.parseDouble(Objects.requireNonNull(response.header(CONTENT_LENGTH, "1"))); + } + + private long write(ResponseBody responseBody, double length) throws IOException { + return writer.write(responseBody.byteStream(), length); } @Override diff --git a/libraries-http-2/src/main/java/com/baeldung/okhttp/download/BinaryFileWriter.java b/libraries-http-2/src/main/java/com/baeldung/okhttp/download/BinaryFileWriter.java index 653cd07449..274778b952 100644 --- a/libraries-http-2/src/main/java/com/baeldung/okhttp/download/BinaryFileWriter.java +++ b/libraries-http-2/src/main/java/com/baeldung/okhttp/download/BinaryFileWriter.java @@ -9,12 +9,14 @@ public class BinaryFileWriter implements AutoCloseable { private static final int CHUNK_SIZE = 1024; private final OutputStream outputStream; + private final ProgressCallable progressCallable; - public BinaryFileWriter(OutputStream outputStream) { + public BinaryFileWriter(OutputStream outputStream, ProgressCallable progressCallable) { this.outputStream = outputStream; + this.progressCallable = progressCallable; } - public long write(InputStream inputStream) throws IOException { + public long write(InputStream inputStream, double length) throws IOException { try (BufferedInputStream input = new BufferedInputStream(inputStream)) { byte[] dataBuffer = new byte[CHUNK_SIZE]; int readBytes; @@ -22,6 +24,7 @@ public class BinaryFileWriter implements AutoCloseable { while ((readBytes = input.read(dataBuffer)) != -1) { totalBytes += readBytes; outputStream.write(dataBuffer, 0, readBytes); + progressCallable.onProgress(totalBytes / length * 100.0); } return totalBytes; } diff --git a/libraries-http-2/src/main/java/com/baeldung/okhttp/download/ProgressCallable.java b/libraries-http-2/src/main/java/com/baeldung/okhttp/download/ProgressCallable.java new file mode 100644 index 0000000000..8e1569a1c2 --- /dev/null +++ b/libraries-http-2/src/main/java/com/baeldung/okhttp/download/ProgressCallable.java @@ -0,0 +1,7 @@ +package com.baeldung.okhttp.download; + +public interface ProgressCallable { + + void onProgress(double progress); + +} diff --git a/libraries-http-2/src/test/java/com/baeldung/okhttp/download/BinaryFileDownloaderIntegrationTest.java b/libraries-http-2/src/test/java/com/baeldung/okhttp/download/BinaryFileDownloaderIntegrationTest.java new file mode 100644 index 0000000000..4fa6c0a466 --- /dev/null +++ b/libraries-http-2/src/test/java/com/baeldung/okhttp/download/BinaryFileDownloaderIntegrationTest.java @@ -0,0 +1,37 @@ +package com.baeldung.okhttp.download; + +import okhttp3.OkHttpClient; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import org.junit.Rule; +import org.junit.Test; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class BinaryFileDownloaderIntegrationTest { + + @Rule + public MockWebServer server = new MockWebServer(); + + @Test + public void givenATextFile_whenDownload_thenExpectFileDownloaded() throws IOException { + String body = "Hello Baeldung Readers!"; + server.enqueue(new MockResponse().setBody(body)); + String fileName = "download.txt"; + BinaryFileWriter writer = new BinaryFileWriter(new FileOutputStream(fileName), progress -> assertEquals(100.0, progress, .0)); + BinaryFileDownloader tested = new BinaryFileDownloader(new OkHttpClient(), writer); + + long downloaded = tested.download(server.url("/greetings").toString()); + + assertEquals(body.length(), downloaded); + File downloadedFile = new File(fileName); + assertTrue(downloadedFile.isFile()); + assertTrue(downloadedFile.delete()); + } + +} diff --git a/libraries-http-2/src/test/java/com/baeldung/okhttp/download/BinaryFileDownloaderUnitTest.java b/libraries-http-2/src/test/java/com/baeldung/okhttp/download/BinaryFileDownloaderUnitTest.java index 6a7d7aca7e..20240febb3 100644 --- a/libraries-http-2/src/test/java/com/baeldung/okhttp/download/BinaryFileDownloaderUnitTest.java +++ b/libraries-http-2/src/test/java/com/baeldung/okhttp/download/BinaryFileDownloaderUnitTest.java @@ -19,6 +19,7 @@ import java.io.InputStream; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyDouble; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -42,12 +43,12 @@ public class BinaryFileDownloaderUnitTest { ResponseBody body = ResponseBody.create("BODY", MediaType.get("application/text")); Response response = createResponse(url, body); when(call.execute()).thenReturn(response); - when(writer.write(any())).thenReturn(1L); + when(writer.write(any(), anyDouble())).thenReturn(1L); try (BinaryFileDownloader tested = new BinaryFileDownloader(client, writer)) { long size = tested.download(url); assertEquals(1L, size); - verify(writer).write(any(InputStream.class)); + verify(writer).write(any(InputStream.class), anyDouble()); } verify(writer).close(); } @@ -62,7 +63,7 @@ public class BinaryFileDownloaderUnitTest { assertThrows(IllegalStateException.class, () -> tested.download(url)); - verify(writer, times(0)).write(any(InputStream.class)); + verify(writer, times(0)).write(any(InputStream.class), anyDouble()); } @NotNull diff --git a/libraries-http-2/src/test/java/com/baeldung/okhttp/download/BinaryFileWriterUnitTest.java b/libraries-http-2/src/test/java/com/baeldung/okhttp/download/BinaryFileWriterUnitTest.java index e4b823f843..19e3d321c2 100644 --- a/libraries-http-2/src/test/java/com/baeldung/okhttp/download/BinaryFileWriterUnitTest.java +++ b/libraries-http-2/src/test/java/com/baeldung/okhttp/download/BinaryFileWriterUnitTest.java @@ -28,8 +28,8 @@ public class BinaryFileWriterUnitTest { InputStream inputStream = mock(InputStream.class); when(inputStream.read(any(), anyInt(), anyInt())).thenReturn(10, -1); - try (BinaryFileWriter tested = new BinaryFileWriter(outputStream)) { - long result = tested.write(inputStream); + try (BinaryFileWriter tested = new BinaryFileWriter(outputStream, progress -> assertEquals(100.0, progress))) { + long result = tested.write(inputStream, 10); assertEquals(10, result); verify(outputStream).write(any(), eq(0), eq(10)); @@ -42,8 +42,8 @@ public class BinaryFileWriterUnitTest { public void givenInputStreamEmpty_whenWrite_thenExpectNotWritten() throws Exception { InputStream inputStream = mock(InputStream.class); - try (BinaryFileWriter tested = new BinaryFileWriter(outputStream)) { - long result = tested.write(inputStream); + try (BinaryFileWriter tested = new BinaryFileWriter(outputStream, progress -> assertEquals(100.0, progress))) { + long result = tested.write(inputStream, 1); assertEquals(0, result); verify(outputStream, times(0)).write(any(), anyInt(), anyInt());