如何使用DefaultHttpClient写入OutputStream?

如何使用org.apache.http.impl.client.DefaultHttpClient获取OutputStream

我正在寻找一个输出流的长字符串。

使用HttpURLConnection您可以像这样实现它:

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

有没有使用类似于我上面的DefaultHttpClient的方法? 如何使用DefaultHttpClient而不是HttpURLConnection写入OutputStream

例如

 DefaultHttpClient client = new DefaultHttpClient(); OutputStream outstream = (get OutputStream somehow) Writer wout = new OutputStreamWriter(out); 

您无法直接从BasicHttpClient获取OutputStream。 您必须创建一个HttpUriRequest对象并为其提供一个封装您要发送的内容的HttpEntity 。 例如,如果输出足够小以适合内存,则可以执行以下操作:

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

如果数据足够大以至于需要对其进行流式传输,则会变得更加困难,因为没有接受OutputStream的HttpEntity实现。 您需要写入临时文件并使用FileEntity或可能设置管道并使用InputStreamEntity

编辑请参阅oleg的答案,了解演示如何流式传输内容的示例代码 – 毕竟您不需要临时文件或管道。

我知道另一个答案已被接受,只是为了记录这是如何用HttpClient写出内容而不在内存中进行中间缓冲。

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

这在android上运行良好。 它也适用于大文件,因为不需要缓冲。

 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 

我编写了Apache的HTTP客户端API [PipedApacheClientOutputStream]的反转,它使用Apache Commons HTTP Client 4.3.4为HTTP POST提供了一个OutputStream接口。

调用代码如下所示:

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

实际上,相同的客户端,执行程序服务和配置可能会在应用程序的整个生命周期中重复使用,因此上面示例中的外部准备和关闭代码可能存在于bootstrap / init和finalization代码中,而不是直接内联OutputStream实例化。

不要以为你可以使用HttpClient获得原始请求输出流。 但您可以使用PostMethod.getParameters()来访问参数值。 另请参阅post方法示例 。