问题描述
我在 JAX-WS 中有一个 Java Web 服务,它从另一个方法返回一个 OutputStream.除了创建一个临时文件,写入它,然后再将它作为 InputStream 重新打开之外,我似乎无法弄清楚如何将 OutputStream 流式传输到返回的 DataHandler 中.举个例子:
I've got a Java web service in JAX-WS that returns an OutputStream from another method. I can't seem to figure out how to stream the OutputStream into the returned DataHandler any other way than to create a temporary file, write to it, then open it back up again as an InputStream. Here's an example:
@MTOM
@WebService
class Example {
@WebMethod
public @XmlMimeType("application/octet-stream") DataHandler service() {
// Create a temporary file to write to
File fTemp = File.createTempFile("my", "tmp");
OutputStream out = new FileOutputStream(fTemp);
// Method takes an output stream and writes to it
writeToOut(out);
out.close();
// Create a data source and data handler based on that temporary file
DataSource ds = new FileDataSource(fTemp);
DataHandler dh = new DataHandler(ds);
return dh;
}
}
主要问题是 writeToOut() 方法可以返回远大于计算机内存的数据.这就是该方法首先使用 MTOM 的原因 - 流式传输数据.我似乎无法理解如何直接从我需要提供给返回的 DataHandler(以及接收 StreamingDataHandler 的客户端)的 OutputStream 中传输数据.
The main issue is that the writeToOut() method can return data that are far larger than the computer's memory. That's why the method is using MTOM in the first place - to stream the data. I can't seem to wrap my head around how to stream the data directly from the OutputStream that I need to provide to the returned DataHandler (and ultimately the client, who receives the StreamingDataHandler).
我尝试过使用 PipedInputStream 和 PipedOutputStream,但这些似乎并不是我所需要的,因为在写入 PipedOutputStream 之后需要返回 DataHandler.
I've tried playing around with PipedInputStream and PipedOutputStream, but those don't seem to be quite what I need, because the DataHandler would need to be returned after the PipedOutputStream is written to.
有什么想法吗?
推荐答案
我找到了答案,正如 Christian 所说的(创建一个新线程来执行 writeToOut()):
I figured out the answer, along the lines that Christian was talking about (creating a new thread to execute writeToOut()):
@MTOM
@WebService
class Example {
@WebMethod
public @XmlMimeType("application/octet-stream") DataHandler service() {
// Create piped output stream, wrap it in a final array so that the
// OutputStream doesn't need to be finalized before sending to new Thread.
PipedOutputStream out = new PipedOutputStream();
InputStream in = new PipedInputStream(out);
final Object[] args = { out };
// Create a new thread which writes to out.
new Thread(
new Runnable(){
public void run() {
writeToOut(args);
((OutputStream)args[0]).close();
}
}
).start();
// Return the InputStream to the client.
DataSource ds = new ByteArrayDataSource(in, "application/octet-stream");
DataHandler dh = new DataHandler(ds);
return dh;
}
}
由于 final
变量,它有点复杂,但据我所知这是正确的.当线程启动时,它在第一次尝试调用 out.write()
时阻塞;同时,输入流返回给客户端,客户端通过读取数据解除写入阻塞.(我之前实现这个解决方案的问题是我没有正确关闭流,因此遇到了错误.)
It is a tad more complex due to final
variables, but as far as I can tell this is correct. When the thread is started, it blocks when it first tries to call out.write()
; at the same time, the input stream is returned to the client, who unblocks the write by reading the data. (The problem with my previous implementations of this solution was that I wasn't properly closing the stream, and thus running into errors.)
这篇关于如何通过管道将 OutputStream 传送到 StreamingDataHandler?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!