如何将InputStream作为Retrofit中的请求主体进行POST?

我正在尝试做一个身体是一个InputStream类似这样的POST:

@POST("/build") @Headers("Content-Type: application/tar") Response build(@Query("t") String tag, @Query("q") boolean quiet, @Query("nocache") boolean nocache, @Body TypedInput inputStream); 

在这种情况下,InputStream来自压缩的tar文件。

发布InputStream的正确方法是什么?

根据http://square.github.io/retrofit/的Multipart部分,您将需要使用TypedOutput而不是TypedInput。 一旦我实现了一个TypedOutput类,下面的他们的分段上传示例工作正常。

TypedInput是一个包含一个InputStream的包装,它包含元数据,如用于请求的长度和内容types。 所有你需要做的就是提供一个实现TypedInput的类,它传递你的inputstream。

 class TarFileInput implements TypedInput { @Override public InputStream in() { return /*your input stream here*/; } // other methods... } 

请确保您根据从中传输内容的文件的types,为length()mimeType()传递适当的返回值。

当您调用build方法时,您也可以select将其作为匿名实现传递。

我想到的唯一解决scheme是使用TypeFile类:

 TypedFile tarTypeFile = new TypedFile("application/tar", myFile); 

和接口(这次没有明确地设置Content-Type头):

 @POST("/build") Response build(@Query("t") String tag, @Query("q") boolean quiet, @Query("nocache") boolean nocache, @Body TypedInput inputStream); 

即使我提供了length(),使用我自己的TypedInput实现也会导致模糊的EOFexception。

 public class TarArchive implements TypedInput { private File file; public TarArchive(File file) { this.file = file; } public String mimeType() { return "application/tar"; } public long length() { return this.file.length(); } public InputStream in() throws IOException { return new FileInputStream(this.file); } } 

另外,在解决这个问题的同时,我尝试使用最新的Apache Http客户端,而不是OkHttp导致“内容长度头已经存在”错误,即使我没有明确设置该头。

我的解决scheme是实现TypedOutput

 public class TypedStream implements TypedOutput{ private Uri uri; public TypedStream(Uri uri){ this.uri = uri; } @Override public String fileName() { return null; } @Override public String mimeType() { return getContentResolver().getType(uri); } @Override public long length() { return -1; } @Override public void writeTo(OutputStream out) throws IOException { Utils.copyStream(getContentResolver().openInputStream(uri), out); } } 
Interesting Posts