如何将 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 读取流(unknowOutputStreamunknowInputStream 变量)。流(据我所知)应该是相同的 - 但如何创建它?

乍一看,我可以使用 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。为了简单起见,我使用了一个)。