我一直在写一个让人们上传的小应用程序。下载文件给我。我已经为这个应用程序添加了一个Web服务,以提供上传/下载功能,但我不太确定我的实现将如何处理大文件。
目前上传和放大的定义下载方法看起来像这样(使用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;
因此文件作为字节数组上传和下载。但是,如果我有一个愚蠢的大小的文件(例如1GB),这肯定会尝试将所有信息放入内存并使我的服务崩溃。
所以我的问题是 - 是否有可能返回某种流?我想这不会是非常独立的操作系统。虽然我知道Web服务背后的理论,但实际的一面是我还需要了解一些信息。
为任何输入干杯, 利
答案 0 :(得分:14)
是的,可以使用Metro。请参阅Large Attachments示例,该示例看起来就像您想要的那样。
JAX-WS RI支持以流方式发送和接收大型附件。
- 在编程模型中使用MTOM和DataHandler。
- 将DataHandler转换为StreamingDataHandler并使用其方法。
- 确保调用StreamingDataHandler.close()并关闭StreamingDataHandler.readOnce()流。
- 在客户端启用HTTP分块。
答案 1 :(得分:6)
Stephen Denne有一个满足您要求的Metro实施。在简短的探讨之后,我的答案将在下面提供。为什么会这样。
使用HTTP作为消息协议构建的大多数Web服务实现都符合REST,因为它们只允许简单的发送 - 接收模式,仅此而已。这极大地提高了互操作性,因为所有各种平台都可以理解这种简单的体系结构(例如,与Web Web服务交谈的Java Web服务)。
如果你想保持这个,你可以提供分块。
boolean uploadFile(String username, String password, String fileName, int currentChunk, int totalChunks, byte[] chunk);
如果你没有按照正确的顺序获得块,这需要一些步法(或者你可以只需要按正确的顺序排列块),但它可能很容易实现。
答案 2 :(得分:3)
当您使用标准化Web服务时,发件人和收件人确实依赖于从一个发送到另一个的XML数据的完整性。这意味着仅在发送最后一个标记时才完成Web服务请求和应答。考虑到这一点,不能将Web服务视为流。
这是合乎逻辑的,因为标准化的Web服务确实依赖于http协议。那个是“无国籍”,会说它的工作方式就像“打开连接......发送请求......接收数据......关闭请求”。无论如何,连接将在最后关闭。所以像流媒体这样的东西不打算在这里使用。或者他在http之上(如网络服务)。
很抱歉,但据我所知,网络服务无法进行流式传输。更糟糕的是:取决于Web服务的实现/配置,byte [] - 数据可能会被转换为Base64而不是CDATA标签,并且请求可能会变得更加膨胀。
P.S。:Yup,正如其他人写的那样,“chuinking”是可能的。但这不是流媒体;-) - 无论如何,它可能对你有帮助。答案 3 :(得分:1)
对于WCF,我认为可以将消息上的成员定义为流并适当地设置绑定 - 我已经看到这项工作与wcf谈论Java Web服务。
您需要在httpTransport配置中设置transferMode =“StreamedResponse”并使用mtomMessageEncoding(需要在配置中使用自定义绑定部分)。
我认为一个限制是,如果您想要流式传输(哪种有意义),您只能拥有一个邮件正文成员。
答案 4 :(得分:1)
Apache CXF支持发送和接收流。
答案 5 :(得分:1)
我讨厌将其分解为那些认为无法使用流式网络服务的人,但实际上,所有的http请求都是基于流的。每个对网站进行GET的浏览器都是基于流的。每次调用Web服务都是基于流的。是的,全部。我们在实现服务或页面的层面上没有注意到这一点,因为较低级别的架构正在为您处理这个问题 - 但它正在完成。
你有没有注意到在浏览器中有时需要一段时间来获取一个页面 - 浏览器只是不停地显示沙漏?那是因为浏览器正在等待流。
流是mime /类型必须在实际数据之前发送的原因 - 它只是浏览器的字节流,如果你没有告诉它是什么,它将无法识别照片。这也是为什么你必须在发送之前传递二进制文件的大小 - 浏览器将无法分辨图像停止的位置并且页面再次被拾取。
这只是客户端的字节流。如果你想自己证明这一点,只需在处理请求的任何时候保持输出流并关闭()它。你会炸毁一切。浏览器将立即停止显示沙漏,并将显示“无法找到”或“在服务器上重置连接”或其他此类消息。
很多人都不知道所有这些东西都是基于流的节目,只是在它上面分层了多少东西。有些人会说太多东西 - 我就是其中之一。
祝你好运,快乐发展 - 放松肩膀!
答案 6 :(得分:0)
一种方法是添加 uploadFileChunk (byte [] chunkData,int size,int offset,int totalSize)方法(或类似的东西),上传部分文件和服务器将其写入磁盘。
答案 7 :(得分:0)
请记住,Web服务请求基本上归结为单个HTTP POST。
如果您查看.NET中.ASMX文件的输出,它会准确显示POST请求和响应的内容。
正如@Guvante所提到的那样,Chunking将是最接近你想要的东西。我认为您可以实现自己的Web客户端代码来处理TCP / IP并将内容流式传输到您的应用程序中,但至少可以说这很复杂。
答案 8 :(得分:0)
答案 9 :(得分:0)
Java RMIIO库提供了跨RMI处理RemoteInputStream - 我们只需要RMI,但您应该能够调整代码以适应其他类型的RMI。这可能对您有所帮助 - 特别是如果您可以在用户端使用小型应用程序。该库的开发目的是能够限制推送到服务器的数据大小,以避免完全符合您描述的情况 - 通过填充RAM或磁盘实际上是DOS攻击。
使用RMIIO库,服务器端可以决定它愿意提取多少数据,使用HTTP PUT和POST,客户端可以做出决定,包括推送的速率。
答案 10 :(得分:0)
是的,网络服务可以进行流式传输。我使用Apache Axis2和MTOM创建了一个Web服务,以支持从XML呈现PDF文档。由于生成的文件可能非常大,因此流式传输非常重要,因为我们不希望将其全部保存在内存中。在streaming SOAP attachments.
上查看Oracle的文档或者,您可以自己完成,tomcat将创建Chunked标头。这是流式传输的弹簧控制器功能的一个例子。
@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();
}
答案 11 :(得分:0)
实际上并不难“处理TCP / IP并将内容流入您的应用程序”。试试这个......
class MyServlet extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response)
{
response.getOutputStream().println("Hello World!");
}
}
这就是它的全部内容。在上面的代码中,您已经响应了从浏览器发送的HTTP GET请求,并在文本“Hello World!”中返回该浏览器。
请记住“Hello World!”是无效的HTML,因此您最终可能会在浏览器上出现错误,但实际上就是它的全部内容。
祝你好运!
罗德尼