我有在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");
}

}

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top