从资源上传okhttp的二进制文件

dab*_*uck 17 android okhttp

我需要使用okhttp将apk中捆绑的二进制文件上传到服务器.使用urlconnection,您只需获取资产的输入流,然后将其放入您的请求中.但是,okhttp只提供上传字节数组,字符串或文件的选项.由于您无法获取apk中捆绑的资产的文件路径,因此将文件复制到本地文件目录的唯一选项(我宁愿不这样做)然后将文件提供给okhttp?有没有办法简单地使用assetinputstream直接向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);
    }
 }
}
Run Code Online (Sandbox Code Playgroud)

我对这种方法唯一关心的是inputstream.available()对于内容长度的不可靠性.静态构造函数是为了匹配okhttp的内部实现

Mig*_*gne 36

您可能无法使用库直接执行此操作,但您可以创建一个小实用程序类来为您执行此操作.然后,您可以在任何需要的地方重复使用它.

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);
                }
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

然后就这样简单地使用它

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());    
Run Code Online (Sandbox Code Playgroud)

此示例代码基于代码.替换Assets文件名和MediaType您自己的名称.

  • 您是否真的对RequestBody的实现有任何连接问题?根据“呼叫”在连接问题时处理重试的方式,“写到”可能会被多次调用,这会因为流关闭而崩溃。 (2认同)