リソースからokhttpを使用してバイナリファイルをアップロードする 質問する

リソースからokhttpを使用してバイナリファイルをアップロードする 質問する

okhttp を使用して、apk にバンドルされているバイナリ ファイルをサーバーにアップロードする必要があります。urlconnection を使用すると、アセットへの入力ストリームを取得し、それをリクエストに組み込むことができます。ただし、okhttp では、バイト配列、文字列、またはファイルのアップロード オプションのみが提供されます。apk にバンドルされているアセットのファイル パスを取得できないため、ファイルをローカル ファイル ディレクトリにコピーし (これは避けたい)、そのファイルを okhttp に渡すしか方法はありませんか? アセット入力ストリームを使用して Web サーバーに直接リクエストを送信する方法はないのでしょうか?

編集:受け入れられた回答を使用しましたが、静的ユーティリティクラスを作成する代わりに、単にRequestBodyをサブクラス化しました。

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

このアプローチで唯一気になるのは、content-lengthに対するinputstream.available()の信頼性の低さです。静的コンストラクタはokhttpの内部実装と一致させる必要があります。

ベストアンサー1

ライブラリを使用して直接実行することはできないかもしれませんが、代わりに実行する小さなユーティリティ クラスを作成することはできます。その後、必要な場所でそれを簡単に再利用できます。

public class RequestBodyUtil {

    public static RequestBody create(final MediaType mediaType, final InputStream inputStream) {
        return new RequestBody() {
            @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();

MediaType MEDIA_TYPE_MARKDOWN
        = MediaType.parse("text/x-markdown; charset=utf-8");

InputStream inputStream = getAssets().open("README.md");

RequestBody requestBody = RequestBodyUtil.create(MEDIA_TYPE_MARKDOWN, inputStream);
Request request = new Request.Builder()
        .url("https://api.github.com/markdown/raw")
        .post(requestBody)
        .build();

Response response = client.newCall(request).execute();
if (!response.isSuccessful())
    throw new IOException("Unexpected code " + response);

Log.d("POST", response.body().string());    

このサンプルコードは以下に基づいていますこれコード。Assetsファイル名とをMediaType独自のものに置き換えてください。

おすすめ記事