如何使用OutputStream
获取org.apache.http.impl.client.DefaultHttpClient
?
我希望将一个长字符串写入输出流。
使用HttpURLConnection
,您可以像这样实现它:
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
OutputStream out = connection.getOutputStream();
Writer wout = new OutputStreamWriter(out);
writeXml(wout);
是否有一种方法使用DefaultHttpClient
类似于我上面的方法?如何使用OutputStream
代替DefaultHttpClient
来写HttpURLConnection
?
例如
DefaultHttpClient client = new DefaultHttpClient();
OutputStream outstream = (get OutputStream somehow)
Writer wout = new OutputStreamWriter(out);
答案 0 :(得分:27)
我知道已经接受了另一个答案,只是为了记录,这就是如何用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);
答案 1 :(得分:14)
您无法直接从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);
如果数据足够大,您需要对其进行流式传输,则会变得更加困难,因为没有HttpEntity
实现接受OutputStream。您需要写入临时文件并使用FileEntity
或可能设置管道并使用InputStreamEntity
编辑请参阅oleg的答案,了解演示如何流式传输内容的示例代码 - 毕竟您不需要临时文件或管道。
答案 2 :(得分:3)
这在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
答案 3 :(得分:2)
我写了一个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实例化内联。