Java Web 服务可以返回流吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/132590/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can a web service return a stream?
提问by Lee Theobald
I've been writing a little application that will let people upload & download files to me. I've added a web service to this applciation to provide the upload/download functionality that way but I'm not too sure on how well my implementation is going to cope with large files.
我一直在编写一个小应用程序,可以让人们向我上传和下载文件。我已经向这个应用程序添加了一个 Web 服务,以通过这种方式提供上传/下载功能,但我不太确定我的实现将如何处理大文件。
At the moment the definitions of the upload & download methods look like this (written using Apache CXF):
目前上传和下载方法的定义如下(使用 Apache CXF 编写):
boolean uploadFile(@WebParam(name = "username") String username,
@WebParam(name = "password") String password,
@WebParam(name = "filename") String filename,
@WebParam(name = "fileContents") byte[] fileContents)
throws UploadException, LoginException;
byte[] downloadFile(@WebParam(name = "username") String username,
@WebParam(name = "password") String password,
@WebParam(name = "filename") String filename) throws DownloadException,
LoginException;
So the file gets uploaded and downloaded as a byte array. But if I have a file of some stupid size (e.g. 1GB) surely this will try and put all that information into memory and crash my service.
所以文件作为字节数组上传和下载。但是,如果我有一个愚蠢大小的文件(例如 1GB),这肯定会尝试将所有这些信息放入内存中并使我的服务崩溃。
So my question is - is it possible to return some kind of stream instead? I would imagine this isn't going to be terribly OS independent though. Although I know the theory behind web services, the practical side is something that I still need to pick up a bit of information on.
所以我的问题是 - 是否可以返回某种流?我想这不会非常独立于操作系统。虽然我知道 Web 服务背后的理论,但实际方面我仍然需要了解一些信息。
Cheers for any input, Lee
为任何意见干杯,李
采纳答案by Guvante
Stephen Dennehas a Metro implementation that satisfies your requirement. My answer is provided below after a short explination as to why that is the case.
Stephen Denne有一个满足您要求的 Metro 实现。我的回答是在简要解释为什么会这样之后提供的。
Most Web Service implementations that are built using HTTP as the message protocol are REST compliant, in that they only allow simple send-receive patterns and nothing more. This greatly improves interoperability, as all the various platforms can understand this simple architecture (for instance a Java web service talking to a .NET web service).
大多数使用 HTTP 作为消息协议构建的 Web 服务实现都符合 REST,因为它们只允许简单的发送-接收模式,仅此而已。这极大地提高了互操作性,因为所有各种平台都可以理解这个简单的体系结构(例如,Java Web 服务与 .NET Web 服务通信)。
If you want to maintain this you could provide chunking.
如果你想保持这一点,你可以提供分块。
boolean uploadFile(String username, String password, String fileName, int currentChunk, int totalChunks, byte[] chunk);
This would require some footwork in cases where you don't get the chunks in the right order (Or you can just require the chunks come in the right order), but it would probably be pretty easy to implement.
如果您没有以正确的顺序获得块(或者您可以只要求块以正确的顺序出现),这将需要一些步法,但它可能很容易实现。
回答by Pop Catalin
One way to do it is to add a uploadFileChunk(byte[] chunkData, int size, int offset, int totalSize) method (or something like that) that uploads parts of the file and the servers writes it the to disk.
一种方法是添加一个uploadFileChunk(byte[] chunkData, int size, int offset, int totalSize) 方法(或类似的东西),该方法上传文件的一部分,服务器将其写入磁盘。
回答by Stephen Denne
Yes, it is possible with Metro. See the Large Attachmentsexample, which looks like it does what you want.
是的,地铁可以。请参阅大附件示例,它看起来像您想要的那样。
JAX-WS RI provides support for sending and receiving large attachments in a streaming fashion.
- Use MTOM and DataHandler in the programming model.
- Cast the DataHandler to StreamingDataHandler and use its methods.
- Make sure you call StreamingDataHandler.close() and also close the StreamingDataHandler.readOnce() stream.
- Enable HTTP chunking on the client-side.
JAX-WS RI 支持以流方式发送和接收大型附件。
- 在编程模型中使用 MTOM 和 DataHandler。
- 将 DataHandler 转换为 StreamingDataHandler 并使用其方法。
- 确保您调用 StreamingDataHandler.close() 并关闭 StreamingDataHandler.readOnce() 流。
- 在客户端启用 HTTP 分块。
回答by Georgi
When you use a standardized web service the sender and reciever do rely on the integrity of the XML data send from the one to the other. This means that a web service request and answer only are complete when the last tag was sent. Having this in mind, a web service cannot be treated as a stream.
当您使用标准化的 Web 服务时,发送方和接收方确实依赖于从一个发送到另一个的 XML 数据的完整性。这意味着只有在发送最后一个标签时,Web 服务请求和应答才完成。考虑到这一点,Web 服务不能被视为流。
This is logical because standardized web services do rely on the http-protocol. That one is "stateless", will say it works like "open connection ... send request ... receive data ... close request". The connection will be closed at the end, anyway. So something like streaming is not intended to be used here. Or he layers above http (like web services).
这是合乎逻辑的,因为标准化的 Web 服务确实依赖于 http 协议。那个是“无状态的”,会说它的工作原理类似于“打开连接......发送请求......接收数据......关闭请求”。无论如何,连接将在最后关闭。所以像流这样的东西不打算在这里使用。或者他位于 http 之上(如 Web 服务)。
So sorry, but as far as I can see there is no possibility for streaming in web services. Even worse: depending on the implementation/configuration of a web service, byte[] - data may be translated to Base64 and not the CDATA-tag and the request might get even more bloated.
很抱歉,但据我所知,无法在 Web 服务中进行流式传输。更糟糕的是:根据 Web 服务的实现/配置,byte[] - 数据可能会被转换为 Base64 而不是 CDATA 标签,并且请求可能会变得更加臃肿。
P.S.: Yup, as others wrote, "chuinking" is possible. But this is no streaming as such ;-) - anyway, it may help you.
PS:是的,正如其他人所写,“chuinking”是可能的。但这不是流式传输;-) - 无论如何,它可能对您有所帮助。
回答by Eric Z Beard
Keep in mind that a web service request basically boils down to a single HTTP POST.
请记住,Web 服务请求基本上归结为单个 HTTP POST。
If you look at the output of a .ASMX file in .NET , it shows you exactly what the POST request and response will look like.
如果您查看 .NET 中 .ASMX 文件的输出,它会准确显示 POST 请求和响应的外观。
Chunking, as mentioned by @Guvante, is going to be the closest thing to what you want.
正如@Guvante 所提到的,分块将是最接近你想要的东西。
I suppose you could implement your own web client code to handle the TCP/IP and stream things into your application, but that would be complex to say the least.
我想您可以实现自己的 Web 客户端代码来处理 TCP/IP 并将内容流式传输到您的应用程序中,但这至少可以说很复杂。
回答by Drejc
回答by Kyle Burton
The RMIIOlibrary for Java provides for handing a RemoteInputStream across RMI - we only needed RMI, though you should be able to adapt the code to work over other types of RMI . This may be of help to you - especially if you can have a small application on the user side. The library was developed with the express purpose of being able to limit the size of the data pushed to the server to avoid exactly the type of situation you describe - effectively a DOS attack by filling up ram or disk.
Java的RMIIO库提供了跨 RMI 处理 RemoteInputStream 的功能——我们只需要 RMI,尽管您应该能够调整代码以在其他类型的 RMI 上工作。这可能对您有所帮助 - 特别是如果您可以在用户端拥有一个小型应用程序。开发该库的明确目的是能够限制推送到服务器的数据的大小,以避免您描述的情况类型 - 通过填充内存或磁盘有效地进行 DOS 攻击。
With the RMIIO library, the server side gets to decide how much data it is willing to pull, where with HTTP PUT and POSTs, the client gets to make that decision, including the rate at which it pushes.
使用 RMIIO 库,服务器端可以决定它愿意拉多少数据,使用 HTTP PUT 和 POST,客户端可以做出决定,包括它推送的速率。
回答by Richard
For WCF I think its possible to define a member on a message as stream and set the binding appropriately - I've seen this work with wcf talking to Java web service.
对于 WCF,我认为可以将消息上的成员定义为流并适当地设置绑定 - 我已经看到 wcf 与 Java Web 服务对话的工作。
You need to set the transferMode="StreamedResponse" in the httpTransport configuration and use mtomMessageEncoding (need to use a custom binding section in the config).
您需要在 httpTransport 配置中设置 transferMode="StreamedResponse" 并使用 mtomMessageEncoding(需要在配置中使用自定义绑定部分)。
I think one limitation is that you can only have a single message body member if you want to stream (which kind of makes sense).
我认为一个限制是,如果您想进行流式传输(这很有意义),您只能拥有一个消息正文成员。
回答by Maniganda Prakash
Apache CXFsupports sending and receiving streams.
Apache CXF支持发送和接收流。
回答by nont
Yes, a webservice can do streaming. I created a webservice using Apache Axis2 and MTOM to support rendering PDF documents from XML. Since the resulting files could be quite large, streaming was important because we didn't want to keep it all in memory. Take a look at Oracle's documentation on streaming SOAP attachments.
是的,网络服务可以进行流式传输。我使用 Apache Axis2 和 MTOM 创建了一个 Web 服务,以支持从 XML 呈现 PDF 文档。由于生成的文件可能非常大,因此流式传输很重要,因为我们不想将其全部保存在内存中。查看 Oracle 的有关流式处理 SOAP 附件的文档。
Alternately, you can do it yourself, and tomcat will create the Chunked headers. This is an example of a spring controller function that streams.
或者,您可以自己完成,tomcat 将创建分块标头。这是一个流的 spring 控制器函数的例子。
@RequestMapping(value = "/stream")
public void hellostreamer(HttpServletRequest request, HttpServletResponse response) throws CopyStreamException, IOException
{
response.setContentType("text/xml");
OutputStreamWriter writer = new OutputStreamWriter (response.getOutputStream());
writer.write("this is streaming");
writer.close();
}