如何将 json 内容从 jackson 流式传输到 org.apache.http.entity.InputStreamEntity?
How stream json content from jackson to org.apache.http.entity.InputStreamEntity?
我正在尝试使用 base64 将 json 流式传输到使用 Appache HttpComponents 的 elasticsearch(据我所知)。
对于 json 流,我创建了 JsonGenerator
,但它需要 "some" OutputStream
。要通过 Jest 发送请求,需要从 "some" InputStream
创建 InputStreamEntity
。所以 JsonGenerator
需要写入流和 InputStreamEntity
读取流(unknowOutputStream
和 unknowInputStream
变量)。流(据我所知)应该是相同的 - 但如何创建它?
乍一看,我可以使用 ByteArrayInputStream
之类的东西,但这样我就失去了流式传输,因为它将内容填充到 byte[]
中,因此所有流数据都将存储到内存中。如何创建一个流,该流将只存储一段数据,直到读取该数据。然后hold住另一条数据?
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import org.apache.http.HttpHost;
import org.apache.http.entity.InputStreamEntity;
import org.elasticsearch.client.RestClient;
import java.io.DataOutput;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
public class Exmaple {
public static void main (String[] args) throws Exception {
final InputStream inputStream;
final int size;
RestClient restClient = RestClient.builder(new HttpHost("myHost", 443, "https")).build();
final OutputStream unknowOutputStream;
final InputStream unknowInputStream;
final JsonGenerator generator = new JsonFactory().createGenerator(unknowOutputStream);
generator.writeStartObject();
generator.writeFieldName("content");
generator.writeBinary(inputStream, size);
generator.writeEndObject();
restClient.performRequest(
"POST",
"somepath",
Collections.emptyMap(), new InputStreamEntity(unknowInputStream));
}
}
可能有一个使用 JDK 中的 PipedInputStream / PipedOutputStream 的解决方案,但我想您从 InputStreamEntity
切换到 EntityTemplate
会更简单在 HTTPClient 的 API 中。
EntityTemplate
是一个与 ContentProducer
一起工作的 HTTP 实体,ContentProducer
的唯一方法是 writeTo(OutputStream)
。这样,您就不必桥接输入流和输出流。
new EntityTemplate(new ContentProducer(
(outputStream) -> {
final JsonGenerator generator = new JsonFactory().createGenerator(outputStream);
generator.write(...);
}
));
(您可能想要创建子类,正确处理异常,...而不是使用 lambda。为了简单起见,我使用了一个)。
我正在尝试使用 base64 将 json 流式传输到使用 Appache HttpComponents 的 elasticsearch(据我所知)。
对于 json 流,我创建了 JsonGenerator
,但它需要 "some" OutputStream
。要通过 Jest 发送请求,需要从 "some" InputStream
创建 InputStreamEntity
。所以 JsonGenerator
需要写入流和 InputStreamEntity
读取流(unknowOutputStream
和 unknowInputStream
变量)。流(据我所知)应该是相同的 - 但如何创建它?
乍一看,我可以使用 ByteArrayInputStream
之类的东西,但这样我就失去了流式传输,因为它将内容填充到 byte[]
中,因此所有流数据都将存储到内存中。如何创建一个流,该流将只存储一段数据,直到读取该数据。然后hold住另一条数据?
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import org.apache.http.HttpHost;
import org.apache.http.entity.InputStreamEntity;
import org.elasticsearch.client.RestClient;
import java.io.DataOutput;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
public class Exmaple {
public static void main (String[] args) throws Exception {
final InputStream inputStream;
final int size;
RestClient restClient = RestClient.builder(new HttpHost("myHost", 443, "https")).build();
final OutputStream unknowOutputStream;
final InputStream unknowInputStream;
final JsonGenerator generator = new JsonFactory().createGenerator(unknowOutputStream);
generator.writeStartObject();
generator.writeFieldName("content");
generator.writeBinary(inputStream, size);
generator.writeEndObject();
restClient.performRequest(
"POST",
"somepath",
Collections.emptyMap(), new InputStreamEntity(unknowInputStream));
}
}
可能有一个使用 JDK 中的 PipedInputStream / PipedOutputStream 的解决方案,但我想您从 InputStreamEntity
切换到 EntityTemplate
会更简单在 HTTPClient 的 API 中。
EntityTemplate
是一个与 ContentProducer
一起工作的 HTTP 实体,ContentProducer
的唯一方法是 writeTo(OutputStream)
。这样,您就不必桥接输入流和输出流。
new EntityTemplate(new ContentProducer(
(outputStream) -> {
final JsonGenerator generator = new JsonFactory().createGenerator(outputStream);
generator.write(...);
}
));
(您可能想要创建子类,正确处理异常,...而不是使用 lambda。为了简单起见,我使用了一个)。