我试图用类似于这样的方式来做一个POST,主体是一个InputStream。
@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文件。
正确的POST输入流的方式是什么?
TypedInput
是一个包装器,围绕着一个 InputStream
的元数据,如长度和内容类型,用于提出请求。你所需要做的就是提供一个实现了 TypedInput
传递你的输入流。
class TarFileInput implements TypedInput {
@Override public InputStream in() {
return /*your input stream here*/;
}
// other methods...
}
请确保你为 length()
和 mimeType()
基于你流媒体内容的文件类型。
你也可以在调用你的 build
方法。
我在这里想到的唯一解决方案是使用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);
使用我自己实现的TypedInput导致了一个模糊的EOF异常,即使我提供了length().
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,结果出现了 "Content-Length header already present "的错误,即使我没有明确设置该头。
根据多部分的 http:/square.github.ioretrofit。 你会希望使用TypedOutput而不是TypedInput。当我实现了一个TypedOutput类后,按照他们的例子进行多部分上传对我来说很好。
我的解决方案是实现 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);
}
}
您可以使用 Multipart
.
@Multipart
@POST("pictures")
suspend fun uploadPicture(
@Part part: MultipartBody.Part
): NetworkPicture
然后在也许你的仓库类中。
suspend fun upload(inputStream: InputStream) {
val part = MultipartBody.Part.createFormData(
"pic", "myPic", RequestBody.create(
MediaType.parse("image/*"),
inputStream.readBytes()
)
)
uploadPicture(part)
}