2017-09-28 5 views
0

J'essaie de streamer json avec base64 dans elasticsearch qui utilise Appache HttpComponents (si je comprends bien).Comment streamer le contenu json de jackson à org.apache.http.entity.InputStreamEntity?

Pour json flux j'ai créé JsonGenerator, mais il faut "quelques" OutputStream. Pour envoyer une requête via Jest il est nécessaire de créer InputStreamEntity à partir de "certains" InputStream. Donc JsonGenerator a besoin de flux pour l'écriture et InputStreamEntity flux pour la lecture (unknowOutputStream et unknowInputStream variables). Le flux (si je comprends bien) devrait être le même - mais comment le créer?

À première vue, je pourrais utiliser quelque chose comme ByteArrayInputStream mais avec cela je perds la diffusion en continu car il va peupler le contenu en byte[] afin que toutes les données de flux seront stockées dans la mémoire. Comment créer un flux qui stockera seulement un morceau de données jusqu'à ce que ces données soient lues. Et puis tenir un autre morceau de données?

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

Répondre

1

Il peut y avoir une solution en utilisant un PipedInputStream/PipedOutputStream du JDK, mais je pense que ce serait plus simple pour vous SWICTH InputStreamEntity-EntityTemplate dans l'API HTTPClient.

EntityTemplate est une entité HTTP qui fonctionne avec un ContentProducer, et la seule méthode du ContentProducer est writeTo(OutputStream). De cette manière, vous n'aurez pas à faire le pont entre les flux d'entrée et de sortie.

new EntityTemplate(new ContentProducer(
    (outputStream) -> { 
     final JsonGenerator generator = new JsonFactory().createGenerator(outputStream); 
     generator.write(...); 
    } 
)); 

(Vous pouvez créer des sous-classes, traiter correctement les exceptions, ... au lieu d'utiliser un lambda. Je un souci de simplicité).