你怎么能管的OutputStream到StreamingDataHandler?
题
我有在JAX-WS Java Web服务,从另一个方法返回的OutputStream。我似乎无法弄清楚如何将流进的OutputStream返回的DataHandler任何其他办法,而不是创建一个临时文件,写入它,然后再回到向上打开它作为一个InputStream。下面是一个例子:
@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的流数据。
我已经试过的PipedInputStream和的PipedOutputStream玩耍,但这些似乎并没有相当我所需要的,因为的DataHandler将需要的PipedOutputStream写入后归还。
任何想法?
解决方案
我想出了答案,沿着基督教说的是线(创建新的线程来执行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()
;同时,输入流返回给客户端,谁通过读取数据放开写。 (我以前的这种解决方案的实现方式的问题是,我没有正确关闭流,并因此运行到错误。)
其他提示
对不起,我做这为C#和不是Java,但我觉得你的方法应该启动一个线程来运行“writeToOut(出);”在parralel。你需要创建一个特殊的流,并把它传递给新的线程,其给出了流writeToOut。启动线程后,你该流对象返回到来电者。
如果你只有一个写入流,并返回后的方法和消耗流,之后返回另一个方法,有没有其他的办法。
课的棘手的部分是得到这样一个-multithreading safe-流的保持:如果内部缓冲器太满它应阻止每一侧
不知道是不是一个Java的管道流适用于这一点。
包装图案? : - 。)
自定义javax.activation.DataSource实现(仅4方法),以便能够做到这一点?
return new DataHandler(new DataSource() {
// implement getOutputStream to return the stream used inside writeToOut()
...
});
我没有使用IDE测试此所以我只是做一个建议。我也需要writeToOut总体布局:-)。
在我的应用程序使用InputStreamDataSource实现,需要的InputStream的构造函数的参数,而不是文件中FileDataSource。它至今有效。
public class InputStreamDataSource implements DataSource {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
private final String name;
public InputStreamDataSource(InputStream inputStream, String name) {
this.name = name;
try {
int nRead;
byte[] data = new byte[16384];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public String getContentType() {
return new MimetypesFileTypeMap().getContentType(name);
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(buffer.toByteArray());
}
@Override
public String getName() {
return name;
}
@Override
public OutputStream getOutputStream() throws IOException {
throw new IOException("Read-only data");
}
}