2012-04-13 14 views
9

¿Cómo obtengo un OutputStream usando org.apache.http.impl.client.DefaultHttpClient?¿Cómo escribo en un OutputStream usando DefaultHttpClient?

Estoy buscando escribir una cadena larga para una secuencia de salida.

Usando HttpURLConnection implementarías que de este modo:

HttpURLConnection connection = (HttpURLConnection)url.openConnection(); 
OutputStream out = connection.getOutputStream(); 
Writer wout = new OutputStreamWriter(out); 
writeXml(wout); 

¿Existe un método que utiliza DefaultHttpClient similar a lo que tengo arriba? ¿Cómo escribiría en un OutputStream usando DefaultHttpClient en lugar de HttpURLConnection?

por ejemplo

DefaultHttpClient client = new DefaultHttpClient(); 

OutputStream outstream = (get OutputStream somehow) 
Writer wout = new OutputStreamWriter(out); 
+0

@KeithRandall, lo he editado. Espero que esté claro ahora. – Fabii

+0

Por favor explique lo que quiere escribir.En ambos ejemplos, getOutputStream() devuelve una secuencia utilizada para enviar datos de solicitud para solicitudes HTTP POST. –

+0

@EugeneKuleshov, ¿Cómo obtengo un Stream de salida usando org.apache.http.impl.client.DefaultHttpClient? – Fabii

Respuesta

13

No se puede obtener un OutputStream desde BasicHttpClient directamente. Debe crear un objeto HttpUriRequest y darle un HttpEntity que encapsula el contenido que desea enviar. Por ejemplo, si su salida es lo suficientemente pequeño como para caber en la memoria, es posible realizar las siguientes acciones:

// Produce the output 
ByteArrayOutputStream out = new ByteArrayOutputStream(); 
Writer writer = new OutputStreamWriter(out, "UTF-8"); 
writeXml(writer); 

// Create the request 
HttpPost request = new HttpPost(uri); 
request.setEntity(new ByteArrayEntity(out.toByteArray())); 

// Send the request 
DefaultHttpClient client = new DefaultHttpClient(); 
HttpResponse response = client.execute(request); 

Si los datos son lo suficientemente grandes que tiene que fluir él, se hace más difícil porque no hay HttpEntity aplicación que acepta un OutputStream. Que había necesidad de escribir en un archivo temporal y utilizar FileEntity o posiblemente creó una tubería y usar la respuesta InputStreamEntity

EDITAR Sede de Oleg para el código de ejemplo que muestra cómo se debe transmitir el contenido - que no es necesario un trabajador temporal archivo o tubería después de todo.

+0

Gracias hombre, muy apreciado. – Fabii

+0

Pregunta: ¿Qué está haciendo writeXml (writer)? Además, ¿cómo está pasando una matriz de bytes a request.setEntity()? –

+0

@MattGrogan está implementando la lógica de la aplicación para producir realmente el contenido que obtiene POSTed para el servidor remoto (copiado del código de ejemplo en la pregunta). – Alex

25

Sé que ya se ha aceptado otra respuesta, solo para el registro, así es como se puede escribir contenido con HttpClient sin memoria intermedia intermedia.

AbstractHttpEntity entity = new AbstractHttpEntity() { 

     public boolean isRepeatable() { 
      return false; 
     } 

     public long getContentLength() { 
      return -1; 
     } 

     public boolean isStreaming() { 
      return false; 
     } 

     public InputStream getContent() throws IOException { 
      // Should be implemented as well but is irrelevant for this case 
      throw new UnsupportedOperationException(); 
     } 

     public void writeTo(final OutputStream outstream) throws IOException { 
      Writer writer = new OutputStreamWriter(outstream, "UTF-8"); 
      writeXml(writer); 
      writer.flush(); 
     } 

    }; 
    HttpPost request = new HttpPost(uri); 
    request.setEntity(entity); 
+0

Bueno - Sabía que tenía que haber una manera simple de transmitir el contenido, simplemente no podía pensar en eso. – Alex

+1

¿Hay algún otro ejemplo de este proceso? ¿Dónde se llama a writeTo? – HGPB

+1

@Haraldo cuando se ejecuta la solicitud, el marco HttpClient llama a 'request.getEntity(). WriteTo()'. Esto significa que no puede escribir un cliente de subproceso único que inicia una POST y luego devuelve su OutputStream a la persona que llama para invocar varias escrituras. – slim

2

Esto funcionó bien en Android. También debería funcionar para archivos grandes, ya que no se necesita almacenamiento en búfer.

PipedOutputStream out = new PipedOutputStream(); 
PipedInputStream in = new PipedInputStream(); 
out.connect(in); 
new Thread() { 
    @Override 
    public void run() { 
     //create your http request 
     InputStreamEntity entity = new InputStreamEntity(in, -1); 
     request.setEntity(entity); 
     client.execute(request,...); 
     //When this line is reached your data is actually written 
    } 
}.start(); 
//do whatever you like with your outputstream. 
out.write("Hallo".getBytes()); 
out.flush(); 
//close your streams 
+0

me funciona a la perfección – mwag

1

me escribió una inversión de la API de cliente HTTP de Apache [PipedApacheClientOutputStream] que proporciona una interfaz Corriente de salida para POST HTTP usando Apache HTTP Client 4.3.4 Commons.

Calling-código es el siguiente:

// Calling-code manages thread-pool 
ExecutorService es = Executors.newCachedThreadPool(
    new ThreadFactoryBuilder() 
    .setNameFormat("apache-client-executor-thread-%d") 
    .build()); 


// Build configuration 
PipedApacheClientOutputStreamConfig config = new  
    PipedApacheClientOutputStreamConfig(); 
config.setUrl("http://localhost:3000"); 
config.setPipeBufferSizeBytes(1024); 
config.setThreadPool(es); 
config.setHttpClient(HttpClientBuilder.create().build()); 

// Instantiate OutputStream 
PipedApacheClientOutputStream os = new  
PipedApacheClientOutputStream(config); 

// Write to OutputStream 
os.write(...); 

try { 
    os.close(); 
} catch (IOException e) { 
    logger.error(e.getLocalizedMessage(), e); 
} 

// Do stuff with HTTP response 
... 

// Close the HTTP response 
os.getResponse().close(); 

// Finally, shut down thread pool 
// This must occur after retrieving response (after is) if interested 
// in POST result 
es.shutdown(); 

Nota- En la práctica el mismo cliente, servicio de ejecutor, y config es probable que se reutiliza en toda la vida de la aplicación, por lo el código de preparación y cierre externo en el ejemplo anterior probablemente se encuentre en el código bootstrap/init y finalización en lugar de estar directamente en línea con la instanciación de OutputStream.

Cuestiones relacionadas