1. 概要

このチュートリアルでは、OkHttpライブラリを使用してバイナリファイルをダウンロードする方法の実際的な例を示します。

2. Mavenの依存関係

まず、ベースライブラリokhttpの依存関係を追加します。

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.9.1</version>
</dependency>

次に、 OkHttpライブラリで実装されたモジュールの統合テストを作成する場合は、mockwebserverライブラリを使用できます。 このライブラリには、サーバーとその応答をモックするためのツールがあります。

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>mockwebserver</artifactId>
    <version>4.9.1</version>
    <scope>test</scope>
</dependency>

3. バイナリファイルのリクエスト

最初に、がファイルをダウンロードする場所からURL をパラメーターとして受け取り、がそのURLのHTTPリクエストを作成して実行するクラスを実装します。

クラスをテスト可能にするために、コンストラクターにOkHttpClientとライターを挿入します。

public class BinaryFileDownloader implements AutoCloseable {

    private final OkHttpClient client;
    private final BinaryFileWriter writer;

    public BinaryFileDownloader(OkHttpClient client, BinaryFileWriter writer) {
        this.client = client;
        this.writer = writer;
    }
}

次に、がURLからファイルをダウンロードするメソッドを実装します。

public long download(String url) throws IOException {
    Request request = new Request.Builder().url(url).build();
    Response response = client.newCall(request).execute();
    ResponseBody responseBody = response.body();
    if (responseBody == null) {
        throw new IllegalStateException("Response doesn't contain a file");
    }
    double length = Double.parseDouble(Objects.requireNonNull(response.header(CONTENT_LENGTH, "1")));
    return writer.write(responseBody.byteStream(), length);
}

ファイルをダウンロードするプロセスには、4つのステップがあります。 URLを使用してリクエストを作成します。 リクエストを実行し、レスポンスを受け取ります。 応答の本文を取得するか、応答の場合は失敗しますヌル。 書きますバイトファイルへの応答の本文の。

4. ローカルファイルへの応答の書き込み

応答から受信したbytesをローカルファイルに書き込むために、 BinaryFileWriter クラスを実装します。このクラスは、がInputStreamとOutputStreamを入力として受け取り、 InputStreamからOutputStreamへ。

OutputStream がコンストラクターに挿入され、クラスをテストできるようになります。

public class BinaryFileWriter implements AutoCloseable {

    private final OutputStream outputStream;

    public BinaryFileWriter(OutputStream outputStream) {
        this.outputStream = outputStream;
    }
}

次に、コンテンツをInputStreamからOutputStreamにコピーするメソッドを実装します。 このメソッドは、最初にInputStreamBufferedInputStreamでラップして、一度にさらにバイトを読み取ることができるようにします。 次に、InputStreamからbytesを一時的に格納するデータバッファを準備します。

最後に、バッファリングされたデータをWriteOutputStreamに書き込みます。 InputStream に読み取るデータがある限り、これを行います。

public long write(InputStream inputStream) throws IOException {
    try (BufferedInputStream input = new BufferedInputStream(inputStream)) {
        byte[] dataBuffer = new byte[CHUNK_SIZE];
        int readBytes;
        long totalBytes = 0;
        while ((readBytes = input.read(dataBuffer)) != -1) {
            totalBytes += readBytes;
            outputStream.write(dataBuffer, 0, readBytes);
        }
        return totalBytes;
    }
}

5. ファイルのダウンロードの進行状況を取得する

場合によっては、ファイルのダウンロードの進行状況をユーザーに通知したいことがあります。

まず、機能インターフェイスを作成する必要があります。

public interface ProgressCallback {
    void onProgress(double progress);
}

次に、BinaryFileWriterクラスで使用します。 これにより、すべてのステップで、ダウンローダーがこれまでに書き込んだ合計バイトが得られます。

まず、ProgressCallbackをフィールドとしてライタークラスに追加します。 次に、writeメソッドをが応答の長さをパラメーターとして受け取るように更新します。 これは、進捗状況を計算するのに役立ちます。

次に、これまでに記述された totalByteslength:から計算されたprogress を使用して、onProgressメソッドを呼び出します。

public class BinaryFileWriter implements AutoCloseable {
    private final ProgressCallback progressCallback;
    public long write(InputStream inputStream, double length) {
        //...
        progressCallback.onProgress(totalBytes / length * 100.0);
    }
}

最後に、BinaryFileDownloaderクラスを合計応答長でwriteメソッドを呼び出すように更新します。 Content-Length ヘッダーから応答の長さを取得し、それをwriteメソッドに渡します。

public class BinaryFileDownloader {
    public long download(String url) {
        double length = getResponseLength(response);
        return write(responseBody, length);
    }
    private double getResponseLength(Response response) {
        return Double.parseDouble(Objects.requireNonNull(response.header(CONTENT_LENGTH, "1")));
    }
}

6. 結論

この記事では、OkHttpライブラリを使用してURLからバイナリファイルをダウンロードする簡単で実用的な例を実装しました。

ファイルダウンロードアプリケーションの完全な実装と単体テストについては、GitHubでプロジェクトを確認してください。