2012-04-13 16 views
9

Come ottengo un OutputStream utilizzando org.apache.http.impl.client.DefaultHttpClient?Come scrivere su un OutputStream utilizzando DefaultHttpClient?

Sto cercando di scrivere una stringa lunga su un flusso di output.

Utilizzando HttpURLConnection si implementa in questo modo:

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

C'è un metodo che utilizza DefaultHttpClient simile a quello che ho sopra? Come scrivere ad un OutputStream utilizzando DefaultHttpClient anziché HttpURLConnection?

es

DefaultHttpClient client = new DefaultHttpClient(); 

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

@KeithRandall, l'ho modificato. Speriamo sia chiaro ora. – Fabii

+0

Spiega cosa vuoi scrivere.In entrambi gli esempi, getOutputStream() restituisce uno stream utilizzato per inviare i dati di richiesta per le richieste HTTP POST. –

+0

@EugeneKuleshov, Come ottengo un flusso di output utilizzando org.apache.http.impl.client.DefaultHttpClient? – Fabii

risposta

13

Non è possibile ottenere direttamente un OutputStream da BasicHttpClient. Devi creare un oggetto HttpUriRequest e assegnargli uno HttpEntity che incapsula il contenuto che desideri inviare. Per esempio, se l'output è abbastanza piccolo da stare in memoria, si potrebbe effettuare le seguenti operazioni:

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

Se i dati sono abbastanza grande che è necessario per lo streaming, diventa più difficile perché non c'è HttpEntity implementazione che accetta un OutputStream. Avresti bisogno di scrivere in un file temporaneo e utilizzare FileEntity o, eventualmente istituito un tubo e utilizzare risposta InputStreamEntity

EDIT Sede di Oleg per il codice di esempio che illustra la modalità di streaming il contenuto - non hai bisogno di una temperatura file o pipe dopo tutto.

+0

Grazie amico, molto apprezzato. – Fabii

+0

Domanda: cosa sta facendo questo writeXml (writer)? Inoltre, come stai passando un array di byte a request.setEntity()? –

+0

@MattGrogan sta implementando la logica dell'applicazione per produrre effettivamente il contenuto che viene inviato POST al server remoto (copiato dal codice di esempio nella domanda). – Alex

25

So che un'altra risposta è già stata accettata, solo per la cronologia questo è il modo in cui è possibile scrivere contenuti con HttpClient senza buffer intermedi in memoria.

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

Nice - Sapevo che doveva esserci un modo semplice per lo streaming dei contenuti, semplicemente non potevo pensarci. – Alex

+1

C'è qualche altro esempio di questo processo? Dove viene scritto per essere chiamato? – HGPB

+1

@Haraldo quando viene eseguita la richiesta, il framework HttpClient chiama 'request.getEntity(). WriteTo()'. Ciò significa che non è possibile scrivere un client a thread singolo che avvia un POST, quindi restituisce il suo OutputStream al chiamante per richiamare più scritture. – slim

2

Questo ha funzionato bene su Android. Dovrebbe funzionare anche per file di grandi dimensioni, poiché non è necessario il buffering.

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

funziona perfettamente per me – mwag

1

ho scritto un'inversione di API client HTTP Apache [PipedApacheClientOutputStream] che fornisce un'interfaccia OutputStream per HTTP POST usando Apache Commons HTTP del client 4.3.4.

Calling-codice simile a questo:

// 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- In pratica lo stesso cliente, servizio di esecutore e di configurazione sarà probabilmente essere riutilizzato per tutta la durata dell'applicazione, in modo il prep esterno e il codice di chiusura dell'esempio precedente risiederanno probabilmente in bootstrap/init e nel codice di finalizzazione piuttosto che direttamente in linea con l'istanza OutputStream.

Problemi correlati