当前位置: 首页 > 知识库问答 >
问题:

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

谭桐
2023-03-14

我需要使用okhttp将捆绑在apk中的二进制文件上传到服务器。使用urlconnection,您可以简单地获得资产的inputstream,然后将其放入您的请求中。但是,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);
    }
 }
}

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

共有3个答案

丌官炎彬
2023-03-14

使用史努比api的方式太容易了:一行代码,如果你排除标识符定义:)

URI uri = ...;
Path fileToUpload = ...;
Snoopy.builder()
      .config(SnoopyConfig.defaults())
      .build()
      .post(uri)
      .followRedirects(true)
      .failIfNotSuccessfulResponse(true)
      .body(fileToUpload)
      .consumeAsString();

https://bitbucket.org/abuwandi/snoopy

仍然没有android版本,但即将发布。。。

邴俊达
2023-03-14

我知道很晚了,但总比没有好。

这里的诀窍是,如果您不知道数据的大小,您可以跳过content-length标头,并将其替换为Http1.1传输编码:Chuncked

欲了解更多信息,请阅读https://www.oracle.com/technical-resources/articles/javame/chunking.html

邢令
2023-03-14

您可能无法直接使用库来实现这一点,但您可以创建一个小的实用程序类来为您实现这一功能。然后,您可以在任何需要的地方重复使用它。

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

此示例代码基于此代码。将Asset文件名和MediaType替换为您自己的。

 类似资料:
  • 我在android应用程序中使用OKHTTP客户端进行网络连接。 接受下面的回答。我修改过的代码:

  • 下面是一个上传二进制文件的例子,WebService类的代码如下: package service; import java.io.InputStream; import java.io.OutputStream; import java.io.FileOutputStream; import javax.activation.DataHandler; public class 

  • 问题内容: 我正在使用Flash录制音频并将其上传到节点服务器。Flash客户端是jrecorder的变体。当用户完成录制后,将使用POST请求(而不是表单,因为Flash无法创建文件)来上传音频,并将音频ByteArray作为POST请求的数据(请参见此处的更多信息)。 我可以使用下面的代码在Node- land上正确接收文件,但是发出的音频被破坏了,您听不到任何声音。话虽如此,该文件的内容可以

  • 正如上面的问题所描述的,我正在尝试将一个文件从okhttp3上传到服务器。 我总是收到‘你没有选择一个文件上传’在我的方法从codeIgniter部分。 这是我的代码 Android: 服务器代码: 我做错了什么?谢谢!

  • 我有问题与费恩客户端。我只需要发送一个文件,我不想使用多部分MIME类型(因为我认为一个文件没有必要)。我可以通过创建编码器到字节数组来做到这一点,但我想使用一些流。 我如何编写接受一些java流并将其发送而不将文件数据缓冲到内存的Feign编码器。使用Feign客户端是否可以进行这种二进制传输? 我看到一些使用多部分文件的示例,它使用了“多部分/表单数据”,但我不想使用多部分。 有可能写这样一个

  • 它应该很简单:我必须发送文件和一些字符串值。但我想不出怎么做。 根据我发现的一些样本,我首先尝试了以下内容: 它给我一个“400错误请求”错误。 我做错了什么? 编辑:顺便说一句,上面的“getfile()”返回一个File对象。其余的参数都是字符串和int。